Skip to content

Commit

Permalink
Implement resize transformed region (#1421)
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <[email protected]>
  • Loading branch information
Pablete1234 authored Nov 3, 2024
1 parent 3dd6af7 commit 2e4165e
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ public void trigger(MatchPlayer player) {
}
for (int i = 0; i < inv.getSize(); i++) {
ItemStack current = inv.getItem(i);
if (current != null && matcher.matches(current)) enchant(current, level);
if (current != null && matcher.matches(current)) {
enchant(current, level);
// Makes item sync with client instantly
inv.setItem(i, current);
}
}
}

Expand Down
5 changes: 0 additions & 5 deletions core/src/main/java/tc/oc/pgm/kits/KitParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -459,11 +459,6 @@ else if (stack.getAmount() != 1)
boolean ignoreEnchantments =
XMLUtils.parseBoolean(Node.fromAttr(parent, "ignore-enchantments"), ignoreMetadata);

if (ignoreMetadata && (!ignoreName || !ignoreEnchantments)) {
throw new InvalidXMLException(
"Cannot ignore metadata but respect name or enchantments", parent);
}

return new ItemMatcher(
stack, amount, ignoreDurability, ignoreMetadata, ignoreName, ignoreEnchantments);
}
Expand Down
13 changes: 13 additions & 0 deletions core/src/main/java/tc/oc/pgm/regions/RegionParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@
import tc.oc.pgm.util.XMLParser;
import tc.oc.pgm.util.xml.InvalidXMLException;
import tc.oc.pgm.util.xml.Node;
import tc.oc.pgm.util.xml.XMLFluentParser;
import tc.oc.pgm.util.xml.XMLUtils;

public abstract class RegionParser implements XMLParser<Region, RegionDefinition> {

protected final Map<String, Method> methodParsers;
protected final MapFactory factory;
protected final XMLFluentParser parser;

public RegionParser(MapFactory factory) {
this.factory = factory;
this.methodParsers = MethodParsers.getMethodParsersForClass(getClass());
this.parser = factory.getParser();
}

@Override
Expand Down Expand Up @@ -291,6 +294,16 @@ public MirroredRegion parseMirror(Element el) throws InvalidXMLException {
return new MirroredRegion(this.parseChildren(el), origin, normal);
}

@MethodParser("resize")
public ResizedRegion parseResize(Element el) throws InvalidXMLException {
Region child = this.parseChildren(el);
Vector min = parser.vector(el, "min").attr().required();
Vector max = parser.vector(el, "max").attr().required();
boolean relative = parser.parseBool(el, "relative").attr().orFalse();
validate(child, BlockBoundedValidation.INSTANCE, new Node(el));
return new ResizedRegion(child, min, max, relative);
}

@MethodParser("everywhere")
public EverywhereRegion parseEverywhere(Element el) throws InvalidXMLException {
return EverywhereRegion.INSTANCE;
Expand Down
69 changes: 69 additions & 0 deletions core/src/main/java/tc/oc/pgm/regions/ResizedRegion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package tc.oc.pgm.regions;

import org.bukkit.util.Vector;
import tc.oc.pgm.api.region.Region;
import tc.oc.pgm.util.math.TransformMatrix;

public class ResizedRegion extends TransformedRegion {
private final Vector min, max;
private final boolean relative;
private TransformMatrix matrix;
private TransformMatrix inverse;

public ResizedRegion(Region region, Vector min, Vector max, boolean relative) {
super(region);
this.min = min;
this.max = max;
this.relative = relative;
}

@Override
protected Vector transform(Vector point) {
if (matrix == null) ensureInitialized();
return matrix.transform(point);
}

@Override
protected Vector untransform(Vector point) {
if (inverse == null) ensureInitialized();
return inverse.transform(point);
}

@Override
public Bounds getBounds() {
ensureInitialized();
return super.getBounds();
}

private void ensureInitialized() {
if (matrix != null) return;

var oldBounds = region.getBounds();
if (oldBounds.isEmpty() || !oldBounds.isBlockFinite()) {
this.bounds = oldBounds;
this.matrix = this.inverse = TransformMatrix.identity();
return;
}

var oldSize = oldBounds.getSize();

if (relative) {
min.multiply(oldSize);
max.multiply(oldSize);
}

this.bounds =
new Bounds(oldBounds.getMin().subtract(min), oldBounds.getMax().add(max));
var newSize = bounds.getSize();

this.matrix = TransformMatrix.concat(
TransformMatrix.untranslate(oldBounds.getMin()),
TransformMatrix.scale(newSize.clone().divide(oldSize)),
TransformMatrix.translate(bounds.getMin()));

this.inverse = TransformMatrix.concat(
TransformMatrix.untranslate(bounds.getMin()),
TransformMatrix.scale(oldSize.clone().divide(newSize)),
TransformMatrix.translate(oldBounds.getMin()));
}
}
2 changes: 1 addition & 1 deletion core/src/main/java/tc/oc/pgm/shops/menu/Payment.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public boolean hasPayment(PlayerInventory inventory) {

public boolean matches(ItemStack item) {
return this.item != null
? Materials.itemsSimilar(item, this.item, true, false)
? Materials.itemsSimilar(item, this.item, true)
: item.getType() == currency;
}
}
13 changes: 13 additions & 0 deletions core/src/main/java/tc/oc/pgm/util/xml/XMLFluentParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import tc.oc.pgm.util.xml.parsers.Builder;
import tc.oc.pgm.util.xml.parsers.FilterBuilder;
import tc.oc.pgm.util.xml.parsers.ItemBuilder;
import tc.oc.pgm.util.xml.parsers.NumberBuilder;
import tc.oc.pgm.util.xml.parsers.PrimitiveBuilder;
import tc.oc.pgm.util.xml.parsers.ReferenceBuilder;
import tc.oc.pgm.util.xml.parsers.RegionBuilder;
Expand Down Expand Up @@ -74,6 +75,18 @@ protected String parse(String text) throws TextException {
};
}

public NumberBuilder<Integer> parseInt(Element el, String... prop) {
return number(Integer.class, el, prop);
}

public NumberBuilder<Double> parseDouble(Element el, String... prop) {
return number(Double.class, el, prop);
}

public <T extends Number> NumberBuilder<T> number(Class<T> cls, Element el, String... prop) {
return new NumberBuilder<>(cls, el, prop);
}

public Builder.Generic<Vector> vector(Element el, String... prop) {
return new Builder.Generic<>(el, prop) {
@Override
Expand Down
34 changes: 34 additions & 0 deletions core/src/main/java/tc/oc/pgm/util/xml/parsers/NumberBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package tc.oc.pgm.util.xml.parsers;

import org.jdom2.Element;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.util.xml.InvalidXMLException;
import tc.oc.pgm.util.xml.Node;
import tc.oc.pgm.util.xml.XMLUtils;

public class NumberBuilder<T extends Number> extends Builder<T, NumberBuilder<T>> {

private final Class<T> type;
private boolean infinity;

public NumberBuilder(Class<T> type, @Nullable Element el, String... prop) {
super(el, prop);
this.type = type;
}

/** Allow infinity like oo or -oo */
public NumberBuilder<T> inf() {
this.infinity = true;
return this;
}

@Override
protected T parse(Node node) throws InvalidXMLException {
return XMLUtils.parseNumber(node, type, infinity);
}

@Override
protected NumberBuilder<T> getThis() {
return this;
}
}
32 changes: 20 additions & 12 deletions util/src/main/java/tc/oc/pgm/util/inventory/ItemMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ public ItemMatcher(
boolean ignoreMetadata,
boolean ignoreName,
boolean ignoreEnchantments) {
if (ignoreMetadata && (!ignoreName || !ignoreEnchantments))
throw new UnsupportedOperationException(
"Cannot ignore metadata but respect name or enchantments");

this.ignoreDurability = ignoreDurability;

Expand All @@ -36,20 +33,31 @@ public ItemMatcher(
this.base = stripMeta(base);
}

private ItemStack stripMeta(ItemStack item) {
ItemMeta meta = item.getItemMeta();
if (meta == null || (!ignoreMetadata && !(ignoreEnchantments && meta.hasEnchants())))
return item;
private ItemStack stripMeta(final ItemStack item) {
// No modification needed
if (!item.hasItemMeta() || (!ignoreMetadata && !ignoreName && !ignoreEnchantments)) return item;

item = item.clone();
if (ignoreMetadata) item.setItemMeta(null);
else item.getEnchantments().keySet().forEach(item::removeEnchantment);
var newItem = item.clone();
if (ignoreMetadata) {
// Strip all meta, then re-add if needed
newItem.setItemMeta(null);

return item;
// Restore name or enchants
if (!ignoreName) newItem.getItemMeta().setDisplayName(item.getItemMeta().getDisplayName());
if (!ignoreEnchantments) newItem.addUnsafeEnchantments(item.getEnchantments());
} else {
// Strip only specific parts
ItemMeta meta = item.getItemMeta();

if (ignoreName) meta.setDisplayName(null);
if (ignoreEnchantments) item.getEnchantments().keySet().forEach(item::removeEnchantment);
}

return newItem;
}

public boolean matches(ItemStack query) {
return Materials.itemsSimilar(base, stripMeta(query), ignoreDurability, ignoreName)
return Materials.itemsSimilar(base, stripMeta(query), ignoreDurability)
&& amount.contains(query.getAmount());
}
}
31 changes: 3 additions & 28 deletions util/src/main/java/tc/oc/pgm/util/material/Materials.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ static boolean isSolid(Material material) {
return material != null && material.isSolid() && !SOLID_EXCLUSIONS.matches(material);
}

static boolean itemsSimilar(
ItemStack first, ItemStack second, boolean skipDur, boolean skipCheckingName) {
static boolean itemsSimilar(ItemStack first, ItemStack second, boolean skipDur) {
if (first == second) {
return true;
}
Expand All @@ -107,36 +106,12 @@ static boolean itemsSimilar(
}
final boolean hasMeta1 = first.hasItemMeta();
final boolean hasMeta2 = second.hasItemMeta();
if (!hasMeta1 && !hasMeta2) {
return true;
}
if (!hasMeta1 && !hasMeta2) return true;

final ItemMeta meta1 = hasMeta1 ? first.getItemMeta() : null;
final ItemMeta meta2 = hasMeta2 ? second.getItemMeta() : null;

final String prevName1 = meta1 != null ? meta1.getDisplayName() : null;
final String prevName2 = meta2 != null ? meta2.getDisplayName() : null;
if (skipCheckingName) {
if (meta1 != null) {
meta1.setDisplayName(null);
}
if (meta2 != null) {
meta2.setDisplayName(null);
}
}

try {
return Bukkit.getItemFactory().equals(meta1, meta2);
} finally {
if (skipCheckingName) {
if (meta1 != null) {
meta1.setDisplayName(prevName1);
}
if (meta2 != null) {
meta2.setDisplayName(prevName2);
}
}
}
return Bukkit.getItemFactory().equals(meta1, meta2);
}

static boolean isSolid(MaterialData material) {
Expand Down
Loading

0 comments on commit 2e4165e

Please sign in to comment.