mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 09:59:20 +00:00
Merge branch 'Xiao-MoMi:dev' into dev
This commit is contained in:
@@ -15,7 +15,6 @@ import net.momirealms.craftengine.bukkit.compatibility.viaversion.ViaVersionUtil
|
||||
import net.momirealms.craftengine.bukkit.compatibility.worldedit.WorldEditBlockRegister;
|
||||
import net.momirealms.craftengine.bukkit.font.BukkitFontManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.core.entity.furniture.AbstractExternalModel;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
@@ -25,7 +24,6 @@ import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.WorldManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -55,18 +53,19 @@ public class BukkitCompatibilityManager implements CompatibilityManager {
|
||||
SkriptHook.register();
|
||||
logHook("Skript");
|
||||
Plugin skriptPlugin = getPlugin("Skript");
|
||||
for (BukkitTask task : Bukkit.getScheduler().getPendingTasks()) {
|
||||
if (task.getOwner() == skriptPlugin) {
|
||||
task.cancel();
|
||||
if (VersionHelper.isFolia()) {
|
||||
Bukkit.getGlobalRegionScheduler().run(skriptPlugin, (t) -> {
|
||||
FastNMS.INSTANCE.getBukkitTaskRunnable(task).run();
|
||||
});
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(skriptPlugin, FastNMS.INSTANCE.getBukkitTaskRunnable(task));
|
||||
}
|
||||
}
|
||||
}
|
||||
// This can cause bugs, needs to find a better way
|
||||
// for (BukkitTask task : Bukkit.getScheduler().getPendingTasks()) {
|
||||
// if (task.getOwner() == skriptPlugin) {
|
||||
// task.cancel();
|
||||
// if (VersionHelper.isFolia()) {
|
||||
// Bukkit.getGlobalRegionScheduler().run(skriptPlugin, (t) -> {
|
||||
// FastNMS.INSTANCE.getBukkitTaskRunnable(task).run();
|
||||
// });
|
||||
// } else {
|
||||
// Bukkit.getScheduler().runTask(skriptPlugin, FastNMS.INSTANCE.getBukkitTaskRunnable(task));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,24 +2,30 @@ package net.momirealms.craftengine.bukkit.compatibility.skript;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.clazz.CraftEngineClasses;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsCustomBlock;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsCustomItem;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsFurniture;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.effect.EffPlaceCustomBlock;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.effect.EffPlaceFurniture;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.effect.EffRemoveFurniture;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomBlock;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.expression.ExprBlockCustomBlockID;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.expression.ExprBlockCustomBlockState;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.expression.ExprEntityFurnitureID;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomClick;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomFurniture;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.expression.*;
|
||||
|
||||
public class SkriptHook {
|
||||
|
||||
public static void register() {
|
||||
CraftEngineClasses.register();
|
||||
EvtCustomBlock.register();
|
||||
EvtCustomFurniture.register();
|
||||
EvtCustomClick.register();
|
||||
CondIsCustomBlock.register();
|
||||
CondIsFurniture.register();
|
||||
CondIsCustomItem.register();
|
||||
ExprBlockCustomBlockID.register();
|
||||
ExprItemCustomItemID.register();
|
||||
ExprBlockCustomBlockState.register();
|
||||
ExprCustomItem.register();
|
||||
ExprEntityFurnitureID.register();
|
||||
EffPlaceCustomBlock.register();
|
||||
EffPlaceFurniture.register();
|
||||
|
||||
@@ -8,6 +8,7 @@ import ch.njol.skript.registrations.Classes;
|
||||
import ch.njol.yggdrasil.Fields;
|
||||
import net.momirealms.craftengine.core.block.BlockStateParser;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UnsafeBlockStateMatcher;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.StreamCorruptedException;
|
||||
@@ -68,5 +69,59 @@ public class CraftEngineClasses {
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
Classes.registerClass(new ClassInfo<>(UnsafeBlockStateMatcher.class, "unsafeblockstatematcher")
|
||||
.user("unsafe block state matcher")
|
||||
.name("Unsafe Block State Matcher")
|
||||
.serializer(new Serializer<>() {
|
||||
@Override
|
||||
public Fields serialize(UnsafeBlockStateMatcher o) {
|
||||
Fields f = new Fields();
|
||||
f.putObject("unsafeblockstatematcher", o.toString());
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(UnsafeBlockStateMatcher o, Fields f) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnsafeBlockStateMatcher deserialize(Fields f) throws StreamCorruptedException {
|
||||
String data = f.getObject("unsafeblockstatematcher", String.class);
|
||||
assert data != null;
|
||||
try {
|
||||
return UnsafeBlockStateMatcher.deserialize(data);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new StreamCorruptedException("Invalid block matcher: " + data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mustSyncDeserialization() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canBeInstantiated() {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.parser(new Parser<>() {
|
||||
@Override
|
||||
public String toString(UnsafeBlockStateMatcher o, int flags) {
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVariableNameString(UnsafeBlockStateMatcher o) {
|
||||
return "unsafeblockstatematcher:" + o.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UnsafeBlockStateMatcher parse(String s, ParseContext context) {
|
||||
return UnsafeBlockStateMatcher.deserialize(s);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.condition;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.conditions.base.PropertyCondition;
|
||||
import ch.njol.skript.lang.Condition;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CondIsCustomItem extends Condition {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerCondition(CondIsCustomItem.class,
|
||||
"%itemstacks% (is|are) custom item(s)",
|
||||
"%itemstacks% (is|are)(n't| not) custom item(s)");
|
||||
}
|
||||
|
||||
private Expression<ItemStack> items;
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
return items.check(event, CraftEngineItems::isCustomItem, isNegated());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return PropertyCondition.toString(this, PropertyCondition.PropertyType.BE, event, debug, items, "itemstack");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
items = (Expression<ItemStack>) expressions[0];
|
||||
setNegated(matchedPattern > 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,9 @@ import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Effect;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.skript.util.Direction;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -4,10 +4,11 @@ import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Literal;
|
||||
import ch.njol.skript.lang.SkriptEvent;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.util.StringUtils;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockPlaceEvent;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UnsafeBlockStateMatcher;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -18,21 +19,21 @@ import java.util.Arrays;
|
||||
public class EvtCustomBlock extends SkriptEvent {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEvent("Break Custom Block", EvtCustomBlock.class, CustomBlockBreakEvent.class, "[customblock] (break[ing]|1¦min(e|ing)) [[of] %-strings%]")
|
||||
Skript.registerEvent("Break Custom Block", EvtCustomBlock.class, CustomBlockBreakEvent.class, "(break[ing]|1¦min(e|ing)) [[of] %-unsafeblockstatematchers%]")
|
||||
.description("Called when a custom block is broken by a player. If you use 'on mine', only events where the broken block dropped something will call the trigger.");
|
||||
Skript.registerEvent("Place Custom Block", EvtCustomBlock.class, CustomBlockPlaceEvent.class, "[customblock] (plac(e|ing)|build[ing]) [[of] %-strings%]")
|
||||
Skript.registerEvent("Place Custom Block", EvtCustomBlock.class, CustomBlockPlaceEvent.class, "(plac(e|ing)|build[ing]) [[of] %-unsafeblockstatematchers%]")
|
||||
.description("Called when a player places a custom block.");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Literal<String> blocks;
|
||||
private String[] blockArray;
|
||||
private Literal<UnsafeBlockStateMatcher> blocks;
|
||||
private UnsafeBlockStateMatcher[] blockArray;
|
||||
private boolean mine = false;
|
||||
|
||||
@Override
|
||||
public boolean init(Literal<?>[] args, int matchedPattern, SkriptParser.ParseResult parser) {
|
||||
if (args[0] != null) {
|
||||
blocks = ((Literal<String>) args[0]);
|
||||
blocks = ((Literal<UnsafeBlockStateMatcher>) args[0]);
|
||||
blockArray = blocks.getAll();
|
||||
}
|
||||
mine = parser.mark == 1;
|
||||
@@ -49,19 +50,16 @@ public class EvtCustomBlock extends SkriptEvent {
|
||||
if (blocks == null)
|
||||
return true;
|
||||
|
||||
String blockType;
|
||||
String blockState;
|
||||
ImmutableBlockState state;
|
||||
if (event instanceof CustomBlockBreakEvent customBlockBreakEvent) {
|
||||
blockType = customBlockBreakEvent.customBlock().id().toString();
|
||||
blockState = customBlockBreakEvent.blockState().toString();
|
||||
state = customBlockBreakEvent.blockState();
|
||||
} else if (event instanceof CustomBlockPlaceEvent customBlockPlaceEvent) {
|
||||
blockType = customBlockPlaceEvent.customBlock().id().toString();
|
||||
blockState = customBlockPlaceEvent.blockState().toString();
|
||||
state = customBlockPlaceEvent.blockState();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Arrays.stream(blockArray).anyMatch(block -> StringUtils.equals(blockType, block, true) || StringUtils.equals(blockState, block, true));
|
||||
return Arrays.stream(blockArray).anyMatch(block -> block.matches(state));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.event;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.aliases.ItemType;
|
||||
import ch.njol.skript.bukkitutil.ClickEventTracker;
|
||||
import ch.njol.skript.lang.Literal;
|
||||
import ch.njol.skript.lang.SkriptEvent;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockInteractEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UnsafeBlockStateMatcher;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class EvtCustomClick extends SkriptEvent {
|
||||
|
||||
private final static int RIGHT = 1, LEFT = 2, ANY = RIGHT | LEFT;
|
||||
public final static ClickEventTracker interactTracker = new ClickEventTracker(Skript.getInstance());
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEvent("Interact Custom Block Furniture", EvtCustomClick.class, new Class[]{CustomBlockInteractEvent.class, FurnitureInteractEvent.class},
|
||||
"[(" + RIGHT + ":right|" + LEFT + ":left)(| |-)][mouse(| |-)]click[ing] [on %-unsafeblockstatematchers/strings%] [(with|using|holding) %-itemtype%]",
|
||||
"[(" + RIGHT + ":right|" + LEFT + ":left)(| |-)][mouse(| |-)]click[ing] (with|using|holding) %itemtype% on %unsafeblockstatematchers/strings%");
|
||||
}
|
||||
|
||||
private @Nullable Literal<?> type;
|
||||
private @Nullable Literal<ItemType> tools;
|
||||
private int click = ANY;
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
ImmutableBlockState block;
|
||||
String furnitureId;
|
||||
if (event instanceof CustomBlockInteractEvent interactEvent) {
|
||||
furnitureId = null;
|
||||
CustomBlockInteractEvent.Action action = interactEvent.action();
|
||||
int click;
|
||||
switch (action) {
|
||||
case LEFT_CLICK -> click = LEFT;
|
||||
case RIGHT_CLICK -> click = RIGHT;
|
||||
default -> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ((this.click & click) == 0)
|
||||
return false;
|
||||
EquipmentSlot hand = interactEvent.hand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND;
|
||||
if (!interactTracker.checkEvent(interactEvent.getPlayer(), interactEvent, hand)) {
|
||||
return false;
|
||||
}
|
||||
block = interactEvent.blockState();
|
||||
} else if (event instanceof FurnitureInteractEvent interactEvent) {
|
||||
furnitureId = interactEvent.furniture().id().toString();
|
||||
block = null;
|
||||
if ((this.click & RIGHT) == 0)
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
Predicate<ItemType> checker = itemType -> {
|
||||
if (event instanceof CustomBlockInteractEvent event1) {
|
||||
return itemType.isOfType(event1.item());
|
||||
} else if (event instanceof FurnitureInteractEvent event1) {
|
||||
return itemType.isOfType(event1.player().getInventory().getItem(event1.hand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (tools != null && !tools.check(event, checker))
|
||||
return false;
|
||||
|
||||
if (type != null) {
|
||||
return type.check(event, (Predicate<Object>) object -> {
|
||||
if (object instanceof String id && furnitureId != null) {
|
||||
return id.equals(furnitureId);
|
||||
} else if (object instanceof UnsafeBlockStateMatcher matcher && block != null) {
|
||||
return matcher.matches(block);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Literal<?>[] args, int matchedPattern, SkriptParser.ParseResult parseResult) {
|
||||
click = parseResult.mark == 0 ? ANY : parseResult.mark;
|
||||
type = args[matchedPattern];
|
||||
tools = (Literal<ItemType>) args[1 - matchedPattern];
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return switch (click) {
|
||||
case LEFT -> "left";
|
||||
case RIGHT -> "right";
|
||||
default -> "";
|
||||
} + "click" + (type != null ? " on " + type.toString(event, debug) : "") +
|
||||
(tools != null ? " holding " + tools.toString(event, debug) : "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.event;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Literal;
|
||||
import ch.njol.skript.lang.SkriptEvent;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurniturePlaceEvent;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public class EvtCustomFurniture extends SkriptEvent {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEvent("Break Furniture", EvtCustomFurniture.class, FurnitureBreakEvent.class, "(break[ing]) [[of] %-strings%]")
|
||||
.description("Called when a furniture is broken by a player.");
|
||||
Skript.registerEvent("Place Furniture", EvtCustomFurniture.class, FurniturePlaceEvent.class, "(plac(e|ing)|build[ing]) [[of] %-strings%]")
|
||||
.description("Called when a player places a furniture.");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Literal<String> ids;
|
||||
private String[] idArray;
|
||||
|
||||
@Override
|
||||
public boolean init(Literal<?>[] args, int matchedPattern, SkriptParser.ParseResult parser) {
|
||||
if (args[0] != null) {
|
||||
ids = ((Literal<String>) args[0]);
|
||||
idArray = ids.getAll();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
if (ids == null)
|
||||
return true;
|
||||
|
||||
String id;
|
||||
if (event instanceof FurnitureBreakEvent e) {
|
||||
id = e.furniture().id().toString();
|
||||
} else if (event instanceof FurniturePlaceEvent e) {
|
||||
id = e.furniture().id().toString();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Arrays.asList(idArray).contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return "break/place" + (ids != null ? " of " + ids.toString(event, debug) : "");
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import java.util.Optional;
|
||||
public class ExprBlockCustomBlockID extends SimplePropertyExpression<Object, String> {
|
||||
|
||||
public static void register() {
|
||||
register(ExprBlockCustomBlockID.class, String.class, "block[ ]custom block id", "blocks/blockdata/customblockstates");
|
||||
register(ExprBlockCustomBlockID.class, String.class, "custom block id", "blocks/blockdata/customblockstates");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class ExprBlockCustomBlockState extends SimplePropertyExpression<Object, ImmutableBlockState> {
|
||||
|
||||
public static void register() {
|
||||
register(ExprBlockCustomBlockState.class, ImmutableBlockState.class, "block[ ]custom block state", "blocks/blockdata");
|
||||
register(ExprBlockCustomBlockState.class, ImmutableBlockState.class, "custom block[ ]state", "blocks/blockdata");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.ExpressionType;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.skript.lang.util.SimpleExpression;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ExprCustomItem extends SimpleExpression<ItemStack> {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerExpression(ExprCustomItem.class, ItemStack.class, ExpressionType.SIMPLE, "[(the|a)] custom item [with id] %string%");
|
||||
}
|
||||
|
||||
private Expression<String> itemId;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
itemId = (Expression<String>) exprs[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemStack[] get(Event e) {
|
||||
String itemId = this.itemId.getSingle(e);
|
||||
if (itemId == null)
|
||||
return null;
|
||||
return new ItemStack[] {Objects.requireNonNull(CraftEngineItems.byId(Key.of(itemId))).buildItemStack(ItemBuildContext.EMPTY)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ItemStack> getReturnType() {
|
||||
return ItemStack.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event e, boolean debug) {
|
||||
return "the custom item with id " + itemId.toString(e, debug);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,16 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.expressions.base.SimplePropertyExpression;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ExprEntityFurnitureID extends SimplePropertyExpression<Object, String> {
|
||||
|
||||
public static void register() {
|
||||
register(ExprEntityFurnitureID.class, String.class, "entity[ ]furniture id", "entities");
|
||||
register(ExprEntityFurnitureID.class, String.class, "furniture id", "entities");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.aliases.ItemType;
|
||||
import ch.njol.skript.classes.Changer;
|
||||
import ch.njol.skript.expressions.base.SimplePropertyExpression;
|
||||
import ch.njol.util.coll.CollectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ExprItemCustomItemID extends SimplePropertyExpression<Object, String> {
|
||||
|
||||
public static void register() {
|
||||
register(ExprItemCustomItemID.class, String.class, "custom item id", "itemstacks/itemtypes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String convert(Object object) {
|
||||
if (object instanceof ItemStack itemStack)
|
||||
return Optional.ofNullable(CraftEngineItems.byItemStack(itemStack)).map(it -> it.id().toString()).orElse(null);
|
||||
if (object instanceof ItemType itemType) {
|
||||
ItemStack itemStack = new ItemStack(itemType.getMaterial());
|
||||
itemStack.setItemMeta(itemType.getItemMeta());
|
||||
return Optional.ofNullable(CraftEngineItems.byItemStack(itemStack)).map(it -> it.id().toString()).orElse(null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyName() {
|
||||
return "custom item id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends String> getReturnType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] acceptChange(Changer.ChangeMode mode) {
|
||||
return CollectionUtils.array(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void change(Event e, @Nullable Object[] delta, Changer.ChangeMode mode) {
|
||||
Key id = Key.of((String) delta[0]);
|
||||
for (Object item : getExpr().getArray(e)) {
|
||||
if (item instanceof ItemStack itemStack) {
|
||||
Item<ItemStack> item1 = BukkitItemManager.instance().wrap(itemStack);
|
||||
Item<ItemStack> item2 = BukkitItemManager.instance().createWrappedItem(id, null);
|
||||
item1.merge(item2);
|
||||
item1.load();
|
||||
} else if (item instanceof ItemType itemType) {
|
||||
Item<ItemStack> item2 = BukkitItemManager.instance().createWrappedItem(id, null);
|
||||
itemType.setItemMeta(item2.load().getItemMeta());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -24,6 +26,7 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable
|
||||
private final InteractionHand hand;
|
||||
private final Action action;
|
||||
private final BlockFace clickedFace;
|
||||
private final ItemStack item;
|
||||
|
||||
public CustomBlockInteractEvent(@NotNull Player player,
|
||||
@NotNull Location location,
|
||||
@@ -32,7 +35,8 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable
|
||||
@NotNull Block bukkitBlock,
|
||||
@NotNull BlockFace clickedFace,
|
||||
@NotNull InteractionHand hand,
|
||||
@NotNull Action action) {
|
||||
@NotNull Action action,
|
||||
@Nullable ItemStack item) {
|
||||
super(player);
|
||||
this.customBlock = state.owner().value();
|
||||
this.bukkitBlock = bukkitBlock;
|
||||
@@ -42,6 +46,7 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable
|
||||
this.hand = hand;
|
||||
this.action = action;
|
||||
this.clickedFace = clickedFace;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -89,6 +94,12 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable
|
||||
return this.state;
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
@NotNull
|
||||
public ItemStack item() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
|
||||
@@ -70,7 +70,8 @@ public class ItemEventListener implements Listener {
|
||||
block,
|
||||
event.getBlockFace(),
|
||||
event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND,
|
||||
action.isRightClick() ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK
|
||||
action.isRightClick() ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK,
|
||||
event.getItem()
|
||||
);
|
||||
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
||||
event.setCancelled(true);
|
||||
|
||||
@@ -368,11 +368,28 @@ public class BukkitInjector {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEWorld ceWorld, SectionPos pos) {
|
||||
// public synchronized static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEWorld ceWorld, SectionPos pos) {
|
||||
// try {
|
||||
// Object container = FastNMS.INSTANCE.field$LevelChunkSection$states(targetSection);
|
||||
// if (!(container instanceof InjectedPalettedContainerHolder)) {
|
||||
// InjectedPalettedContainerHolder injectedObject = FastNMS.INSTANCE.createInjectedPalettedContainerHolder(container);
|
||||
// injectedObject.ceSection(ceSection);
|
||||
// injectedObject.ceWorld(ceWorld);
|
||||
// injectedObject.cePos(pos);
|
||||
// Reflections.varHandle$PalettedContainer$data.setVolatile(injectedObject, Reflections.varHandle$PalettedContainer$data.get(container));
|
||||
// Reflections.field$LevelChunkSection$states.set(targetSection, injectedObject);
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// CraftEngine.instance().logger().severe("Failed to inject chunk section", e);
|
||||
// }
|
||||
// }
|
||||
|
||||
public static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEWorld ceWorld, SectionPos pos) {
|
||||
try {
|
||||
Object container = FastNMS.INSTANCE.field$LevelChunkSection$states(targetSection);
|
||||
if (!(container instanceof InjectedPalettedContainerHolder)) {
|
||||
InjectedPalettedContainerHolder injectedObject = FastNMS.INSTANCE.createInjectedPalettedContainerHolder(container);
|
||||
if (!clazz$InjectedPalettedContainer.isInstance(container)) {
|
||||
InjectedPalettedContainerHolder injectedObject = (InjectedPalettedContainerHolder) Reflections.UNSAFE.allocateInstance(clazz$InjectedPalettedContainer);
|
||||
varHandle$InjectedPalettedContainer$target.set(injectedObject, container);
|
||||
injectedObject.ceSection(ceSection);
|
||||
injectedObject.ceWorld(ceWorld);
|
||||
injectedObject.cePos(pos);
|
||||
|
||||
@@ -48,16 +48,11 @@ public class BlockStateHolder {
|
||||
return propertyMap.entrySet().stream()
|
||||
.map(entry -> {
|
||||
Property<?> property = entry.getKey();
|
||||
return property.name() + "=" + formatValue(property, entry.getValue());
|
||||
return property.name() + "=" + Property.formatValue(property, entry.getValue());
|
||||
})
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T extends Comparable<T>> String formatValue(Property<T> property, Comparable<?> value) {
|
||||
return property.valueName((T) value);
|
||||
}
|
||||
|
||||
public Collection<Property<?>> getProperties() {
|
||||
return Collections.unmodifiableSet(propertyMap.keySet());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
import net.momirealms.craftengine.core.util.StringReader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BlockStateMatcher {
|
||||
private final List<Pair<Property<?>, Comparable<?>>> properties;
|
||||
private final Key id;
|
||||
|
||||
public BlockStateMatcher(Key id, List<Pair<Property<?>, Comparable<?>>> properties) {
|
||||
this.properties = properties;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean matches(ImmutableBlockState state) {
|
||||
if (!state.owner().value().id.equals(this.id)) {
|
||||
return false;
|
||||
}
|
||||
for (Pair<Property<?>, Comparable<?>> pair : this.properties) {
|
||||
if (!state.get(pair.left()).equals(pair.right())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (properties.isEmpty()) {
|
||||
return id.toString();
|
||||
}
|
||||
return id + "[" + getPropertiesAsString() + "]";
|
||||
}
|
||||
|
||||
public String getPropertiesAsString() {
|
||||
return properties.stream()
|
||||
.map(entry -> {
|
||||
Property<?> property = entry.left();
|
||||
return property.name() + "=" + Property.formatValue(property, entry.right());
|
||||
})
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
@Nullable
|
||||
public static BlockStateMatcher deserialize(@NotNull String data) {
|
||||
StringReader reader = StringReader.simple(data);
|
||||
String blockIdString = reader.readUnquotedString();
|
||||
if (reader.canRead() && reader.peek() == ':') {
|
||||
reader.skip();
|
||||
blockIdString = blockIdString + ":" + reader.readUnquotedString();
|
||||
}
|
||||
Optional<Holder.Reference<CustomBlock>> optional = BuiltInRegistries.BLOCK.get(Key.from(blockIdString));
|
||||
if (optional.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Holder<CustomBlock> holder = optional.get();
|
||||
List<Pair<Property<?>, Comparable<?>>> properties = new ArrayList<>();
|
||||
if (reader.canRead() && reader.peek() == '[') {
|
||||
reader.skip();
|
||||
while (reader.canRead()) {
|
||||
reader.skipWhitespace();
|
||||
if (reader.peek() == ']') break;
|
||||
String propertyName = reader.readUnquotedString();
|
||||
reader.skipWhitespace();
|
||||
if (!reader.canRead() || reader.peek() != '=') {
|
||||
return null;
|
||||
}
|
||||
reader.skip();
|
||||
reader.skipWhitespace();
|
||||
String propertyValue = reader.readUnquotedString();
|
||||
Property<?> property = holder.value().getProperty(propertyName);
|
||||
if (property != null) {
|
||||
Optional<?> optionalValue = property.optional(propertyValue);
|
||||
if (optionalValue.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
properties.add(Pair.of(property, (Comparable<?>) optionalValue.get()));
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
reader.skipWhitespace();
|
||||
if (reader.canRead() && reader.peek() == ',') {
|
||||
reader.skip();
|
||||
}
|
||||
}
|
||||
reader.skipWhitespace();
|
||||
if (reader.canRead() && reader.peek() == ']') {
|
||||
reader.skip();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new BlockStateMatcher(holder.value().id(), properties);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
import net.momirealms.craftengine.core.util.StringReader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class UnsafeBlockStateMatcher {
|
||||
private final List<Pair<String, String>> matchers;
|
||||
private final Key id;
|
||||
|
||||
public UnsafeBlockStateMatcher(Key id, List<Pair<String, String>> matchers) {
|
||||
this.id = id;
|
||||
this.matchers = matchers;
|
||||
}
|
||||
|
||||
public boolean matches(ImmutableBlockState state) {
|
||||
if (!state.owner().value().id.equals(this.id)) {
|
||||
return false;
|
||||
}
|
||||
CustomBlock customBlock = state.owner().value();
|
||||
for (Pair<String, String> matcher : matchers) {
|
||||
Property<?> property = customBlock.getProperty(matcher.left());
|
||||
if (property == null) {
|
||||
return false;
|
||||
}
|
||||
Comparable<?> value = state.get(property);
|
||||
String valueStr = Property.formatValue(property, value);
|
||||
if (!matcher.right().equals(valueStr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (matchers.isEmpty()) {
|
||||
return id.toString();
|
||||
}
|
||||
return id + "[" + matchers.stream()
|
||||
.map(entry -> entry.left() + "=" + entry.right())
|
||||
.collect(Collectors.joining(",")) + "]";
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
@Nullable
|
||||
public static UnsafeBlockStateMatcher deserialize(@NotNull String data) {
|
||||
StringReader reader = StringReader.simple(data);
|
||||
String blockIdString = reader.readUnquotedString();
|
||||
if (reader.canRead() && reader.peek() == ':') {
|
||||
reader.skip();
|
||||
blockIdString = blockIdString + ":" + reader.readUnquotedString();
|
||||
}
|
||||
Optional<Holder.Reference<CustomBlock>> optional = BuiltInRegistries.BLOCK.get(Key.from(blockIdString));
|
||||
if (optional.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Holder<CustomBlock> holder = optional.get();
|
||||
List<Pair<String, String>> properties = new ArrayList<>();
|
||||
if (reader.canRead() && reader.peek() == '[') {
|
||||
reader.skip();
|
||||
while (reader.canRead()) {
|
||||
reader.skipWhitespace();
|
||||
if (reader.peek() == ']') break;
|
||||
String propertyName = reader.readUnquotedString();
|
||||
reader.skipWhitespace();
|
||||
if (!reader.canRead() || reader.peek() != '=') {
|
||||
return null;
|
||||
}
|
||||
reader.skip();
|
||||
reader.skipWhitespace();
|
||||
String propertyValue = reader.readUnquotedString();
|
||||
properties.add(new Pair<>(propertyName, propertyValue));
|
||||
reader.skipWhitespace();
|
||||
if (reader.canRead() && reader.peek() == ',') {
|
||||
reader.skip();
|
||||
}
|
||||
}
|
||||
reader.skipWhitespace();
|
||||
if (reader.canRead() && reader.peek() == ']') {
|
||||
reader.skip();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new UnsafeBlockStateMatcher(holder.value().id(), properties);
|
||||
}
|
||||
}
|
||||
@@ -162,4 +162,9 @@ public abstract class Property<T extends Comparable<T>> {
|
||||
.map(it -> it.apply(property))
|
||||
.orElse(((context, state) -> ImmutableBlockState.with(state, property, property.defaultValue())));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Comparable<T>> String formatValue(Property<T> property, Comparable<?> value) {
|
||||
return property.valueName((T) value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ public record Key(String namespace, String value) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof Key key)) return false;
|
||||
return this.namespace.equals(key.namespace()) && this.value.equals(key.value());
|
||||
// 先比value命中率高
|
||||
return this.value.equals(key.value()) && this.namespace.equals(key.namespace());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G
|
||||
|
||||
# Project settings
|
||||
# Rule: [major update].[feature update].[bug fix]
|
||||
project_version=0.0.51-beta.3
|
||||
project_version=0.0.51
|
||||
config_version=30
|
||||
lang_version=7
|
||||
project_group=net.momirealms
|
||||
|
||||
Reference in New Issue
Block a user