Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow cuboid variables to be used for random #1478

Merged
merged 2 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}
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
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
Loading