Skip to content

Commit

Permalink
Support no-update structure placing (#1419)
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <pabloherrerapalacio@gmail.com>
  • Loading branch information
Pablete1234 committed Nov 30, 2024
1 parent b3bf3ff commit 2c79609
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 123 deletions.
4 changes: 3 additions & 1 deletion core/src/main/java/tc/oc/pgm/action/ActionParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ public FillAction parseFill(Element el, Class<?> scope) throws InvalidXMLExcepti
parser.region(el, "region").blockBounded().orSelf(),
XMLUtils.parseBlockMaterialData(Node.fromRequiredAttr(el, "material")),
parser.filter(el, "filter").orNull(),
parser.parseBool(el, "update").orTrue(),
parser.parseBool(el, "events").orFalse());
}

Expand Down Expand Up @@ -414,7 +415,8 @@ public <T extends Filterable<?>> PasteStructureAction<T> parseStructure(
var zFormula = parser.formula(scope, el, "z").required();

var structure = parser.reference(StructureDefinition.class, el, "structure").required();
var update = parser.parseBool(el, "update").orTrue();

return new PasteStructureAction<>(scope, xFormula, yFormula, zFormula, structure);
return new PasteStructureAction<>(scope, xFormula, yFormula, zFormula, structure, update);
}
}
12 changes: 9 additions & 3 deletions core/src/main/java/tc/oc/pgm/action/actions/FillAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,20 @@ public class FillAction extends AbstractAction<Match> {
private final Region region;
private final BlockMaterialData materialData;
private final @Nullable Filter filter;
private final boolean update;
private final boolean events;

public FillAction(
Region region, BlockMaterialData materialData, @Nullable Filter filter, boolean events) {
Region region,
BlockMaterialData materialData,
@Nullable Filter filter,
boolean update,
boolean events) {
super(Match.class);
this.region = region;
this.materialData = materialData;
this.filter = filter;
this.update = update;
this.events = events;
}

Expand All @@ -32,15 +38,15 @@ public void trigger(Match match) {
if (filter != null && filter.query(new BlockQuery(block)).isDenied()) continue;

if (!events) {
materialData.applyTo(block, true);
materialData.applyTo(block, update);
} else {
BlockState newState = block.getState();
materialData.applyTo(newState);

BlockFormEvent event = new BlockFormEvent(block, newState);
match.callEvent(event);
if (event.isCancelled()) continue;
newState.update(true, true);
newState.update(true, update);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,26 @@ public class PasteStructureAction<T extends Filterable<?>> extends AbstractActio
private final Formula<T> yformula;
private final Formula<T> zformula;
private final FeatureReference<StructureDefinition> structureReference;
private final boolean update;

public PasteStructureAction(
Class<T> scope,
Formula<T> xformula,
Formula<T> yformula,
Formula<T> zformula,
FeatureReference<StructureDefinition> structureReference) {
FeatureReference<StructureDefinition> structureReference,
boolean update) {
super(scope);
this.xformula = xformula;
this.yformula = yformula;
this.zformula = zformula;
this.structureReference = structureReference;
this.update = update;
}

@Override
public void trigger(T t) {
BlockVector placeLocation = new BlockVector(
xformula.applyAsDouble(t), yformula.applyAsDouble(t), zformula.applyAsDouble(t));

structureReference.get().getStructure(t.getMatch()).placeAbsolute(placeLocation);
var loc = new BlockVector(xformula.apply(t), yformula.apply(t), zformula.apply(t));
structureReference.get().getStructure(t.getMatch()).placeAbsolute(loc, update);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,26 @@ public ControlPointBlockDisplay(Match match, ControlPoint controlPoint) {
if (progressDisplayRegion == null) {
this.progressDisplayRegion = null;
} else {
this.progressDisplayRegion =
FiniteBlockRegion.fromWorld(
progressDisplayRegion, match.getWorld(), visualMaterials, match.getMap().getProto());
this.progressDisplayRegion = FiniteBlockRegion.fromWorld(
progressDisplayRegion,
match.getWorld(),
visualMaterials,
match.getMap().getProto());
snapshot.saveRegion(progressDisplayRegion);
}

if (controllerDisplayRegion == null) {
this.controllerDisplayRegion = null;
} else {
Filter controllerDisplayFilter =
this.progressDisplayRegion == null
? visualMaterials
: AllFilter.of(visualMaterials, new InverseFilter(progressDisplayRegion));

this.controllerDisplayRegion =
FiniteBlockRegion.fromWorld(
controllerDisplayRegion,
match.getWorld(),
controllerDisplayFilter,
match.getMap().getProto());
Filter controllerDisplayFilter = this.progressDisplayRegion == null
? visualMaterials
: AllFilter.of(visualMaterials, new InverseFilter(progressDisplayRegion));

this.controllerDisplayRegion = FiniteBlockRegion.fromWorld(
controllerDisplayRegion,
match.getWorld(),
controllerDisplayFilter,
match.getMap().getProto());
snapshot.saveRegion(controllerDisplayRegion);
}
}
Expand All @@ -76,7 +76,7 @@ public ControlPointBlockDisplay(Match match, ControlPoint controlPoint) {
public void setController(Competitor controllingTeam) {
if (this.controllingTeam != controllingTeam && this.controllerDisplayRegion != null) {
if (controllingTeam == null) {
snapshot.placeBlocks(this.controllerDisplayRegion, null);
snapshot.placeBlocks(this.controllerDisplayRegion, null, false);
} else {
COLOR_UTILS.setColor(
match.getWorld(),
Expand All @@ -97,7 +97,7 @@ private void setBlock(BlockVector pos, Competitor team) {
if (team != null) {
COLOR_UTILS.setColor(block, team.getDyeColor());
} else {
snapshot.getOriginalMaterial(pos).applyTo(block, true);
snapshot.getOriginalMaterial(pos).applyTo(block, false);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/java/tc/oc/pgm/snapshot/BudgetWorldEdit.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class BudgetWorldEdit {
* @param region region where the blocks were when they got saved
* @param offset the offset to add when placing blocks
*/
public void placeBlocks(Region region, BlockVector offset) {
public void placeBlocks(Region region, BlockVector offset, boolean update) {
if (offset == null) offset = NO_OFFSET;
for (BlockData blockData : snapshot.getMaterials(region)) {
blockData.applyTo(blockData.getBlock(world, offset), true);
blockData.applyTo(blockData.getBlock(world, offset), update);
}
}

Expand All @@ -42,12 +42,12 @@ public void placeBlocks(Region region, BlockVector offset) {
* @param region The region to remove blocks from
* @param offset an offset to add to the region coordinates if the blocks were offset when placed
*/
public void removeBlocks(Region region, BlockVector offset) {
public void removeBlocks(Region region, BlockVector offset, boolean update) {
if (offset == null) offset = NO_OFFSET;
for (BlockData blockData : snapshot.getMaterials(region)) {
Block block = blockData.getBlock(world, offset);
// Ignore if already air
if (!block.getType().equals(Material.AIR)) block.setType(Material.AIR);
if (!block.getType().equals(Material.AIR)) block.setType(Material.AIR, update);
}
}
}
8 changes: 4 additions & 4 deletions core/src/main/java/tc/oc/pgm/snapshot/WorldSnapshot.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ public void saveRegion(Region region) {
region.getChunkPositions().forEach(cv -> this.saveSnapshot(cv, null));
}

public void placeBlocks(Region region, BlockVector offset) {
worldEdit.placeBlocks(region, offset);
public void placeBlocks(Region region, BlockVector offset, boolean update) {
worldEdit.placeBlocks(region, offset, update);
}

public void removeBlocks(Region region, BlockVector offset) {
worldEdit.removeBlocks(region, offset);
public void removeBlocks(Region region, BlockVector offset, boolean update) {
worldEdit.removeBlocks(region, offset, update);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/tc/oc/pgm/structure/DynamicStructure.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ public DynamicStructureDefinition getDefinition() {
public void place() {
if (placed) return;
placed = true;
structure.place(offset);
structure.place(offset, definition.shouldUpdate());
}

/** Remove the structure from the world */
public void clear() {
if (!placed) return;
placed = false;

snapshot.placeBlocks(region, new BlockVector());
snapshot.placeBlocks(region, new BlockVector(), definition.shouldUpdate());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@ public class DynamicStructureDefinition extends SelfIdentifyingFeatureDefinition
private final Filter passive;
private final @Nullable BlockVector position;
private final @NotNull BlockVector offset;
private final boolean update;

DynamicStructureDefinition(
String id,
StructureDefinition structure,
Filter trigger,
Filter passive,
boolean update,
@Nullable BlockVector position,
@Nullable BlockVector offset) {
super(id);
this.structure = assertNotNull(structure);
this.trigger = assertNotNull(trigger);
this.passive = assertNotNull(passive);
this.update = update;
this.position = position;
this.offset = offset == null ? new BlockVector() : offset;
}
Expand Down Expand Up @@ -60,6 +63,11 @@ public Filter getPassive() {
return passive;
}

/** @return If this dynamic should generate block updates when placing */
public boolean shouldUpdate() {
return update;
}

/**
* The offset to use when placing/clearing the structure. Can not be used if the position
* attribute is used.
Expand Down
13 changes: 6 additions & 7 deletions core/src/main/java/tc/oc/pgm/structure/Structure.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import org.bukkit.Material;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;
import tc.oc.pgm.api.feature.Feature;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.region.Region;
Expand All @@ -28,7 +27,7 @@ public Structure(StructureDefinition definition, Match match, WorldSnapshot snap
match.getMap().getProto());

snapshot.saveRegion(region);
if (definition.clearSource()) snapshot.removeBlocks(region, new BlockVector());
if (definition.clearSource()) snapshot.removeBlocks(region, new BlockVector(), false);
}

@Override
Expand All @@ -45,12 +44,12 @@ public Region getRegion() {
return region;
}

public void place(BlockVector offset) {
snapshot.placeBlocks(region, offset);
public void place(BlockVector offset, boolean update) {
snapshot.placeBlocks(region, offset, update);
}

public void placeAbsolute(BlockVector vector) {
place(new BlockVector(
new Vector(0, 0, 0).subtract(getRegion().getBounds().getBlockMin()).add(vector)));
public void placeAbsolute(BlockVector vector, boolean update) {
vector.subtract(getRegion().getBounds().getBlockMin());
place(vector, update);
}
}
44 changes: 18 additions & 26 deletions core/src/main/java/tc/oc/pgm/structure/StructureModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import java.util.UUID;
import java.util.logging.Logger;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jetbrains.annotations.Nullable;
Expand All @@ -23,14 +22,9 @@
import tc.oc.pgm.api.module.exception.ModuleLoadException;
import tc.oc.pgm.filters.FilterMatchModule;
import tc.oc.pgm.filters.matcher.StaticFilter;
import tc.oc.pgm.filters.parse.DynamicFilterValidation;
import tc.oc.pgm.filters.parse.FilterParser;
import tc.oc.pgm.regions.BlockBoundedValidation;
import tc.oc.pgm.regions.RegionParser;
import tc.oc.pgm.snapshot.SnapshotMatchModule;
import tc.oc.pgm.util.Version;
import tc.oc.pgm.util.xml.InvalidXMLException;
import tc.oc.pgm.util.xml.Node;
import tc.oc.pgm.util.xml.XMLUtils;

public class StructureModule implements MapModule<StructureMatchModule> {
Expand Down Expand Up @@ -65,50 +59,48 @@ public StructureModule parse(MapFactory factory, Logger logger, Document doc)
Version proto = factory.getProto();
if (proto.isOlderThan(MapProtos.FILTER_FEATURES)) return null;

FilterParser filters = factory.getFilters();
RegionParser regions = factory.getRegions();
var parser = factory.getParser();

final Map<String, StructureDefinition> structures = new HashMap<>();
for (Element el : XMLUtils.flattenElements(doc.getRootElement(), "structures", "structure")) {
final StructureDefinition definition =
new StructureDefinition(
XMLUtils.getRequiredAttribute(el, "id").getValue(),
XMLUtils.parseVector(el.getAttribute("origin"), (Vector) null),
regions.parseProperty(el, "region", BlockBoundedValidation.INSTANCE),
XMLUtils.parseBoolean(el.getAttribute("air"), false),
XMLUtils.parseBoolean(el.getAttribute("clear"), true));
final StructureDefinition definition = new StructureDefinition(
parser.string(el, "id").attr().required(),
parser.vector(el, "origin").attr().orNull(),
parser.region(el, "region").blockBounded().required(),
parser.parseBool(el, "air").attr().orFalse(),
parser.parseBool(el, "clear").attr().orTrue());

structures.put(definition.getId(), definition);
factory.getFeatures().addFeature(el, definition);
}

final List<DynamicStructureDefinition> dynamics = new ArrayList<>();
for (Element el : XMLUtils.flattenElements(doc.getRootElement(), "structures", "dynamic")) {
String id = el.getAttributeValue("id");
if (id == null) id = UUID.randomUUID().toString();
String id =
parser.string(el, "id").attr().optional(() -> UUID.randomUUID().toString());

BlockVector position = XMLUtils.parseBlockVector(Node.fromAttr(el, "location"));
BlockVector offset = XMLUtils.parseBlockVector(Node.fromAttr(el, "offset"));
BlockVector position = parser.blockVector(el, "location").attr().orNull();
BlockVector offset = parser.blockVector(el, "offset").attr().orNull();

if (position != null && offset != null)
throw new InvalidXMLException(
"attributes 'location' and 'offset' cannot be used together", el);

final StructureDefinition structure =
structures.get(XMLUtils.getRequiredAttribute(el, "structure").getValue());
var structure = structures.get(parser.string(el, "structure").attr().required());

Filter trigger, filter;
if (proto.isOlderThan(MapProtos.DYNAMIC_FILTERS)) {
// Legacy maps use "filter" as their trigger
trigger = filters.parseRequiredProperty(el, "filter", DynamicFilterValidation.MATCH);
trigger = parser.filter(el, "filter").dynamic(Match.class).required();
filter = StaticFilter.ALLOW;
} else {
trigger = filters.parseRequiredProperty(el, "trigger", DynamicFilterValidation.MATCH);
filter = filters.parseProperty(el, "filter", StaticFilter.ALLOW);
trigger = parser.filter(el, "trigger").dynamic(Match.class).required();
filter = parser.filter(el, "filter").orAllow();
}
var update = parser.parseBool(el, "update").orTrue();

DynamicStructureDefinition definition =
new DynamicStructureDefinition(id, structure, trigger, filter, position, offset);
DynamicStructureDefinition definition = new DynamicStructureDefinition(
id, structure, trigger, filter, update, position, offset);
dynamics.add(definition);
factory.getFeatures().addFeature(el, definition);
}
Expand Down
Loading

0 comments on commit 2c79609

Please sign in to comment.