Skip to content

Commit

Permalink
Allow cuboid variables to be used for random
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <[email protected]>
  • Loading branch information
Pablete1234 committed Jan 10, 2025
1 parent 96aab3d commit 9cb18a1
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 93 deletions.
19 changes: 15 additions & 4 deletions core/src/main/java/tc/oc/pgm/api/region/Region.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ default boolean contains(BlockVector blockPos) {
return this.contains((Vector) BlockVectors.center(blockPos));
}

/**
* Gets a random point contained within this region.
*
* @param match to use.
* @return Random point within this region.
* @throws UnsupportedOperationException if this region cannot generate random points
*/
default Vector getRandom(Random match) {
throw new UnsupportedOperationException(
"Cannot generate a random point in " + this.getClass().getSimpleName());
}

/**
* Iterate over all the blocks inside this region.
*
Expand Down Expand Up @@ -123,13 +135,12 @@ default Static getStatic(World world) {
/**
* Gets a random point contained within this region.
*
* @param random Random generator to use.
* @param match to use.
* @return Random point within this region.
* @throws UnsupportedOperationException if this region cannot generate random points
*/
default Vector getRandom(Random random) {
throw new UnsupportedOperationException(
"Cannot generate a random point in " + this.getClass().getSimpleName());
default Vector getRandom(Match match) {
return getStatic(match).getRandom(match.getRandom());
}

/** Does this region contain a finite number of blocks? */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ public void onParticipantLeave(PlayerPartyChangeEvent event) {
boolean dropped = false;
for (Dropoff dropoff : dropoffs) {
if (dropoff.getFilter().query(oldParty).isAllowed()) {
drop(
enderchest,
dropoff.getRegion().getRandom(match.getRandom()).toLocation(match.getWorld()));
drop(enderchest, dropoff.getRegion().getRandom(match).toLocation(match.getWorld()));
dropped = true;
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import tc.oc.pgm.util.xml.Node;
import tc.oc.pgm.util.xml.XMLUtils;
import tc.oc.pgm.variables.Variable;
import tc.oc.pgm.variables.VariablesModule;
import tc.oc.pgm.variables.VariableParser;

public class FeatureFilterParser extends FilterParser {

Expand Down Expand Up @@ -91,7 +91,7 @@ public Filter parseDeny(Element el) throws InvalidXMLException {

private static final Pattern INLINE_VARIABLE =
Pattern.compile("(%VAR%)(?:\\[(\\d+)])?\\s*=\\s*(%RANGE%|%NUM%)"
.replace("%VAR%", VariablesModule.Factory.VARIABLE_ID.pattern())
.replace("%VAR%", VariableParser.VARIABLE_ID.pattern())
.replace("%RANGE%", XMLUtils.RANGE_DOTTED.pattern())
.replace("%NUM%", "-?\\d*\\.?\\d+"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public boolean canFail() {

@Override
public Location getPoint(Match match, @Nullable Entity entity) {
Vector pos = this.region.getRandom(match.getRandom());
Vector pos = this.region.getRandom(match);
PointProviderLocation location =
makeSafe(new PointProviderLocation(match.getWorld(), pos.getX(), pos.getY(), pos.getZ()));

Expand Down
87 changes: 38 additions & 49 deletions core/src/main/java/tc/oc/pgm/portals/PortalModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@
import tc.oc.pgm.filters.parse.DynamicFilterValidation;
import tc.oc.pgm.regions.RFAContext;
import tc.oc.pgm.regions.RFAScope;
import tc.oc.pgm.regions.RandomPointsValidation;
import tc.oc.pgm.regions.RegionFilterApplication;
import tc.oc.pgm.regions.RegionModule;
import tc.oc.pgm.regions.RegionParser;
import tc.oc.pgm.regions.TranslatedRegion;
import tc.oc.pgm.regions.Union;
import tc.oc.pgm.util.xml.InvalidXMLException;
Expand Down Expand Up @@ -70,36 +68,34 @@ public Collection<Class<? extends MapModule<?>>> getSoftDependencies() {
@Override
public PortalModule parse(MapFactory factory, Logger logger, Document doc)
throws InvalidXMLException {
var parser = factory.getParser();
Set<Portal> portals = Sets.newHashSet();
RegionParser regionParser = factory.getRegions();
RFAContext.Builder rfaContext = factory.getModule(RegionModule.class).getRFAContextBuilder();

for (Element portalEl : XMLUtils.flattenElements(doc.getRootElement(), "portals", "portal")) {

PortalTransform transform =
PortalTransform.piecewise(
parseDoubleProvider(portalEl, "x", RelativeDoubleProvider.ZERO),
parseDoubleProvider(portalEl, "y", RelativeDoubleProvider.ZERO),
parseDoubleProvider(portalEl, "z", RelativeDoubleProvider.ZERO),
parseDoubleProvider(portalEl, "yaw", RelativeDoubleProvider.ZERO),
parseDoubleProvider(portalEl, "pitch", RelativeDoubleProvider.ZERO));
PortalTransform transform = PortalTransform.piecewise(
parseDoubleProvider(portalEl, "x", RelativeDoubleProvider.ZERO),
parseDoubleProvider(portalEl, "y", RelativeDoubleProvider.ZERO),
parseDoubleProvider(portalEl, "z", RelativeDoubleProvider.ZERO),
parseDoubleProvider(portalEl, "yaw", RelativeDoubleProvider.ZERO),
parseDoubleProvider(portalEl, "pitch", RelativeDoubleProvider.ZERO));

Region entrance;
Region.Static entrance;
if (factory.getProto().isOlderThan(MapProtos.MODULE_SUBELEMENT_VERSION)) {
entrance = regionParser.parseChildren(portalEl);
entrance = parser.staticRegion(portalEl).children().orNull();
} else {
entrance = regionParser.parseRegionProperty(portalEl, "region");
entrance = parser.staticRegion(portalEl, "region").orNull();
}

Region exit =
regionParser.parseProperty(portalEl, "destination", RandomPointsValidation.INSTANCE);
Region.Static exit =
parser.staticRegion(portalEl, "destination").randomPoints().orNull();

if (exit != null) {
// If there is an explicit exit region, create a transform for it and combine
// it with the piecewise transform (so angle transforms are still applied).
transform =
PortalTransform.concatenate(
transform, PortalTransform.regional(Optional.ofNullable(entrance), exit));
transform = PortalTransform.concatenate(
transform, PortalTransform.regional(Optional.ofNullable(entrance), exit));
} else if (entrance != null && transform.invertible()) {
// If no exit region is specified, but there is an entrance region, and the
// piecewise transform is invertible, infer the exit region from the entrance region.
Expand Down Expand Up @@ -132,15 +128,12 @@ public PortalModule parse(MapFactory factory, Logger logger, Document doc)
}

// Figure out the forward trigger, from the dynamic filters or entrance region
Filter forwardFinal =
Stream.of(forward, transit, entrance)
.filter(Objects::nonNull)
.findFirst()
.orElseThrow(
() ->
new InvalidXMLException(
"Portal must have an entrance region, or one of 'forward' or 'transit' properties",
portalEl));
Filter forwardFinal = Stream.of(forward, transit, entrance)
.filter(Objects::nonNull)
.findFirst()
.orElseThrow(() -> new InvalidXMLException(
"Portal must have an entrance region, or one of 'forward' or 'transit' properties",
portalEl));

// Figure out the (optional) reverse trigger, from dynamic filters or exit region
Filter inverseTransit = transit != null ? new InverseFilter(transit) : null;
Expand All @@ -150,10 +143,9 @@ public PortalModule parse(MapFactory factory, Logger logger, Document doc)

// Portal is always bidirectional if a reverse dynamic filter is specified,
// otherwise it must be enabled explicitly.
final boolean bidirectional =
reverse != null
|| transit != null
|| XMLUtils.parseBoolean(portalEl.getAttribute("bidirectional"), false);
final boolean bidirectional = reverse != null
|| transit != null
|| XMLUtils.parseBoolean(portalEl.getAttribute("bidirectional"), false);
if (bidirectional && !transform.invertible()) {
throw new InvalidXMLException(
"Bidirectional portal must have an invertible transform", portalEl);
Expand Down Expand Up @@ -185,20 +177,19 @@ public PortalModule parse(MapFactory factory, Logger logger, Document doc)
factory.getFeatures().addFeature(portalEl, portal);

if (bidirectional) {
Portal inversePortal =
new Portal(
reverseFinal.orElse(null),
transform.inverse(),
participantFilter,
observerFilter,
sound,
smooth);
Portal inversePortal = new Portal(
reverseFinal.orElse(null),
transform.inverse(),
participantFilter,
observerFilter,
sound,
smooth);
portals.add(inversePortal);
factory.getFeatures().addFeature(portalEl, inversePortal);
}
}

return (portals.size() == 0) ? null : new PortalModule(portals);
return portals.isEmpty() ? null : new PortalModule(portals);
}

/**
Expand All @@ -207,15 +198,13 @@ public PortalModule parse(MapFactory factory, Logger logger, Document doc)
* <p>The region is extended up by 2m to allow for the height of the player.
*/
private static void protectRegion(RFAContext.Builder rfaContext, Region region) {
region =
Union.of(
region,
TranslatedRegion.translate(region, new Vector(0, 1, 0)),
TranslatedRegion.translate(region, new Vector(0, 2, 0)));

rfaContext.prepend(
new RegionFilterApplication(
RFAScope.BLOCK_PLACE, region, StaticFilter.DENY, PROTECT_MESSAGE, false));
region = Union.of(
region,
TranslatedRegion.translate(region, new Vector(0, 1, 0)),
TranslatedRegion.translate(region, new Vector(0, 2, 0)));

rfaContext.prepend(new RegionFilterApplication(
RFAScope.BLOCK_PLACE, region, StaticFilter.DENY, PROTECT_MESSAGE, false));
}

private static DoubleProvider parseDoubleProvider(
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/java/tc/oc/pgm/portals/PortalTransform.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,16 @@ public PortalTransform inverse() {
}
}

static PortalTransform regional(Optional<Region> from, Region to) {
static PortalTransform regional(Optional<Region.Static> from, Region.Static to) {
return new Regional(from, to);
}

class Regional implements PortalTransform {
private final Random random;
private final Optional<Region> from;
private final Region to;
private final Optional<Region.Static> from;
private final Region.Static to;

private Regional(Optional<Region> from, Region to) {
private Regional(Optional<Region.Static> from, Region.Static to) {
this.from = assertNotNull(from);
this.to = assertNotNull(to);
this.random = new Random();
Expand Down
8 changes: 5 additions & 3 deletions core/src/main/java/tc/oc/pgm/regions/StaticValidation.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ public class StaticValidation implements FeatureValidation<RegionDefinition> {

@Override
public void validate(RegionDefinition definition, Node node) throws InvalidXMLException {
if (!definition.isStatic()) {
throw new InvalidXMLException("Cannot use non-static region here", node);
}
if (!definition.isStatic()) throw makeException(node);
}

public static InvalidXMLException makeException(Node node) {
return new InvalidXMLException("Cannot use non-static region here", node);
}
}
8 changes: 7 additions & 1 deletion core/src/main/java/tc/oc/pgm/regions/TransformedRegion.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.bukkit.Location;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.region.Region;
import tc.oc.pgm.api.region.RegionDefinition;

Expand Down Expand Up @@ -76,7 +77,12 @@ public boolean canGetRandom() {
*/
@Override
public Vector getRandom(Random random) {
return this.transform(this.region.getRandom(random));
return this.transform(this.region.getStatic().getRandom(random));
}

@Override
public Vector getRandom(Match match) {
return this.transform(this.region.getRandom(match));
}

protected abstract Vector transform(Vector point);
Expand Down
8 changes: 5 additions & 3 deletions core/src/main/java/tc/oc/pgm/regions/Union.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ public Union(Region... regions) {
}

public static Region of(Region... regions) {
return regions.length == 0
? EmptyRegion.INSTANCE
: regions.length == 1 ? regions[0] : new Union(regions);
return switch (regions.length) {
case 0 -> EmptyRegion.INSTANCE;
case 1 -> regions[0];
default -> new Union(regions);
};
}

public Region[] getRegions() {
Expand Down
7 changes: 6 additions & 1 deletion core/src/main/java/tc/oc/pgm/regions/XMLRegionReference.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,12 @@ public boolean canGetRandom() {

@Override
public Vector getRandom(Random random) {
return get().getRandom(random);
return getStatic().getRandom(random);
}

@Override
public Vector getRandom(Match match) {
return get().getRandom(match);
}

@Override
Expand Down
8 changes: 3 additions & 5 deletions core/src/main/java/tc/oc/pgm/spawner/Spawner.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void tick(Match match, Tick tick) {
if (match.getTick().tick - lastTick >= currentDelay) {
for (Spawnable spawnable : definition.objects) {
final Location location =
definition.spawnRegion.getRandom(match.getRandom()).toLocation(match.getWorld());
definition.spawnRegion.getRandom(match).toLocation(match.getWorld());
spawnable.spawn(location, match);
EFFECTS.spawnFlame(match.getWorld(), location);
spawnedEntities += spawnable.getSpawnCount();
Expand All @@ -65,10 +65,8 @@ private void calculateDelay() {
} else {
long maxDelay = TimeUtils.toTicks(definition.maxDelay);
long minDelay = TimeUtils.toTicks(definition.minDelay);
currentDelay =
(long)
(match.getRandom().nextDouble() * (maxDelay - minDelay)
+ minDelay); // Picks a random tick duration between minDelay and maxDelay
currentDelay = (long) (match.getRandom().nextDouble() * (maxDelay - minDelay)
+ minDelay); // Picks a random tick duration between minDelay and maxDelay
}
lastTick = match.getTick().tick;
}
Expand Down
9 changes: 7 additions & 2 deletions core/src/main/java/tc/oc/pgm/util/xml/XMLFluentParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import tc.oc.pgm.action.ActionParser;
import tc.oc.pgm.api.feature.FeatureDefinition;
import tc.oc.pgm.api.map.factory.MapFactory;
import tc.oc.pgm.api.region.Region;
import tc.oc.pgm.features.FeatureDefinitionContext;
import tc.oc.pgm.filters.Filterable;
import tc.oc.pgm.filters.parse.FilterParser;
Expand Down Expand Up @@ -124,8 +125,12 @@ public FilterBuilder filter(Element el, String... prop) {
return new FilterBuilder(filters, el, prop);
}

public RegionBuilder region(Element el, String... prop) {
return new RegionBuilder(regions, el, prop);
public RegionBuilder<Region> region(Element el, String... prop) {
return new RegionBuilder.OfRegion(regions, el, prop);
}

public RegionBuilder<Region.Static> staticRegion(Element el, String... prop) {
return new RegionBuilder.OfStatic(regions, el, prop);
}

public ItemBuilder item(Element el, String... prop) {
Expand Down
Loading

0 comments on commit 9cb18a1

Please sign in to comment.