mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-28 03:19:14 +00:00
@@ -56,7 +56,7 @@ The code you contribute will be open-sourced under the GPLv3 license. If you pre
|
||||
## Differences Between Versions
|
||||
| Version | Official Support | Max Players | Dev Builds |
|
||||
|-------------------|------------------|-------------|------------|
|
||||
| Community Edition | ❌ No | 20 | ❌ No |
|
||||
| Community Edition | ❌ No | 30 | ❌ No |
|
||||
| Premium Edition | ✔️ Yes | Unlimited | ✔️ Yes |
|
||||
|
||||
### 💖 Support the Developer
|
||||
|
||||
@@ -39,8 +39,6 @@ public class BukkitCompatibilityManager implements CompatibilityManager {
|
||||
private final Map<String, ModelProvider> modelProviders;
|
||||
private final Map<String, LevelerProvider> levelerProviders;
|
||||
private boolean hasPlaceholderAPI;
|
||||
private boolean hasViaVersion;
|
||||
private MythicSkillHelper skillExecute;
|
||||
|
||||
public BukkitCompatibilityManager(BukkitCraftEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -63,26 +61,12 @@ public class BukkitCompatibilityManager implements CompatibilityManager {
|
||||
this.hasPlaceholderAPI = true;
|
||||
logHook("PlaceholderAPI");
|
||||
}
|
||||
// skript
|
||||
if (this.isPluginEnabled("Skript")) {
|
||||
SkriptHook.register();
|
||||
logHook("Skript");
|
||||
Plugin skriptPlugin = getPlugin("Skript");
|
||||
// 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));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
// WorldEdit
|
||||
// FastAsyncWorldEdit
|
||||
if (this.isPluginEnabled("FastAsyncWorldEdit")) {
|
||||
try {
|
||||
this.initFastAsyncWorldEditHook();
|
||||
|
||||
@@ -9,7 +9,7 @@ import io.lumine.mythic.api.skills.SkillCaster;
|
||||
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||
import io.lumine.mythic.bukkit.adapters.BukkitItemStack;
|
||||
import io.lumine.mythic.core.drops.droppables.ItemDrop;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
@@ -38,7 +38,7 @@ public class MythicItemDrop extends ItemDrop implements IItemDrop {
|
||||
if (caster != null && caster.getEntity() instanceof AbstractPlayer abstractPlayer) {
|
||||
Entity bukkitEntity = abstractPlayer.getBukkitEntity();
|
||||
if (bukkitEntity instanceof Player bukkitPlayer) {
|
||||
var player = BukkitCraftEngine.instance().adapt(bukkitPlayer);
|
||||
var player = BukkitAdaptors.adapt(bukkitPlayer);
|
||||
context = ItemBuildContext.of(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class MythicItemDropListener implements Listener {
|
||||
@@ -16,7 +17,7 @@ public class MythicItemDropListener implements Listener {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.javaPlugin());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
|
||||
public void onMythicDropLoad(MythicDropLoadEvent event) {
|
||||
if (!event.getDropName().equalsIgnoreCase("craftengine")) return;
|
||||
String argument = event.getArgument();
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.clazz.CraftEngineClasses;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsCraftEngineHasBeenLoad;
|
||||
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.EvtCraftEngineReload;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomBlock;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomClick;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomFurniture;
|
||||
@@ -16,9 +18,11 @@ public class SkriptHook {
|
||||
|
||||
public static void register() {
|
||||
CraftEngineClasses.register();
|
||||
EvtCraftEngineReload.register();
|
||||
EvtCustomBlock.register();
|
||||
EvtCustomFurniture.register();
|
||||
EvtCustomClick.register();
|
||||
CondIsCraftEngineHasBeenLoad.register();
|
||||
CondIsCustomBlock.register();
|
||||
CondIsFurniture.register();
|
||||
CondIsCustomItem.register();
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.condition;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.doc.Description;
|
||||
import ch.njol.skript.doc.Name;
|
||||
import ch.njol.skript.doc.Since;
|
||||
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.compatibility.skript.event.EvtCraftEngineReload;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Name("CraftEngine has been load")
|
||||
@Description({"Checks CraftEngine has been load."})
|
||||
@Since("1.0")
|
||||
public class CondIsCraftEngineHasBeenLoad extends Condition {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerCondition(CondIsCraftEngineHasBeenLoad.class,
|
||||
"(ce|craft[-]engine) (has been|is) load[ed]",
|
||||
"(ce|craft[-]engine) (has not been|is not) load[ed] [yet]",
|
||||
"(ce|craft[-]engine) (hasn't been|isn't) load[ed] [yet]"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
setNegated(matchedPattern >= 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
boolean beenLoad = EvtCraftEngineReload.hasBeenLoad();
|
||||
return isNegated() ? !beenLoad : beenLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return "craft-engine " + (isNegated() ? "is not" : "is") + " loaded";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -15,8 +15,8 @@ public class CondIsCustomBlock extends Condition {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerCondition(CondIsCustomBlock.class,
|
||||
"%blocks% (is|are) custom block(s)",
|
||||
"%blocks% (is|are)(n't| not) custom block(s)");
|
||||
"%blocks% (is|are) [a[n]] (custom|ce|craft-engine) block[s]",
|
||||
"%blocks% (is|are) (n't| not) [a[n]] (custom|ce|craft-engine) block[s]");
|
||||
}
|
||||
|
||||
private Expression<Block> blocks;
|
||||
|
||||
@@ -1,41 +1,65 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.condition;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.aliases.ItemType;
|
||||
import ch.njol.skript.conditions.base.PropertyCondition;
|
||||
import ch.njol.skript.doc.Description;
|
||||
import ch.njol.skript.doc.Name;
|
||||
import ch.njol.skript.doc.Since;
|
||||
import ch.njol.skript.lang.Condition;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.skript.util.slot.Slot;
|
||||
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;
|
||||
|
||||
@Name("Is CraftEngine Item")
|
||||
@Description({"Checks if the Item is CraftEngine item."})
|
||||
@Since("1.0")
|
||||
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)");
|
||||
"%itemstack/itemtype/slot% (is [a[n]]|are) (custom|ce|craft-engine) item[s]",
|
||||
"%itemstack/itemtype/slot% (isn't|is not|aren't|are not) [a[n]] (custom|ce|craft-engine) 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");
|
||||
}
|
||||
private Expression<?> item;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
items = (Expression<ItemStack>) expressions[0];
|
||||
setNegated(matchedPattern > 1);
|
||||
item = expressions[0];
|
||||
setNegated(matchedPattern == 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
Object single = item.getSingle(event);
|
||||
|
||||
ItemStack checkItemStack = null;
|
||||
if (single instanceof ItemType itemType) {
|
||||
checkItemStack = itemType.getTypes().getFirst().getStack();
|
||||
} else if (single instanceof ItemStack itemStack) {
|
||||
checkItemStack = itemStack;
|
||||
} else if (single instanceof Slot slot) {
|
||||
checkItemStack = slot.getItem();
|
||||
}
|
||||
|
||||
if (checkItemStack == null) return isNegated() ? true : false;
|
||||
|
||||
boolean exists = CraftEngineItems.isCustomItem(checkItemStack);
|
||||
if (!exists) return isNegated() ? true : false;
|
||||
return isNegated() ? false : true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return PropertyCondition.toString(this, PropertyCondition.PropertyType.BE, event, debug, item, "itemtypes");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -15,15 +16,18 @@ public class CondIsFurniture extends Condition {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerCondition(CondIsFurniture.class,
|
||||
"%entities% (is|are) furniture",
|
||||
"%entities% (is|are)(n't| not) furniture");
|
||||
"%entities% (is|are) [a[n]] [(custom|ce|craft-engine)] furniture[s]",
|
||||
"%entities% (is|are) (n't| not) [a[n]] [(custom|ce|craft-engine)] furniture[s]");
|
||||
}
|
||||
|
||||
private Expression<Entity> entities;
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
return entities.check(event, CraftEngineFurniture::isFurniture, isNegated());
|
||||
return entities.check(event, entity -> {
|
||||
BukkitFurniture baseEntity = CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity);
|
||||
return baseEntity != null;
|
||||
}, isNegated());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class EffPlaceCustomBlock extends Effect {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEffect(EffPlaceCustomBlock.class, "place custom block %customblockstates% [%directions% %locations%]");
|
||||
Skript.registerEffect(EffPlaceCustomBlock.class, "place (custom|ce|craft-engine) block %customblockstates% [at] [%directions% %locations%]");
|
||||
}
|
||||
|
||||
private Expression<ImmutableBlockState> blocks;
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class EffPlaceFurniture extends Effect {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEffect(EffPlaceFurniture.class, "place furniture %strings% [%directions% %locations%]");
|
||||
Skript.registerEffect(EffPlaceFurniture.class, "place [(custom|ce|craft-engine)] furniture[s] %strings% [at] [%directions% %locations%]");
|
||||
}
|
||||
|
||||
private Expression<String> furniture;
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class EffRemoveFurniture extends Effect {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEffect(EffRemoveFurniture.class, "remove furniture %entities%");
|
||||
Skript.registerEffect(EffRemoveFurniture.class, "remove [(custom|ce|craft-engine)] furniture %entities%");
|
||||
}
|
||||
|
||||
private Expression<Entity> entities;
|
||||
@@ -22,11 +22,9 @@ public class EffRemoveFurniture extends Effect {
|
||||
@Override
|
||||
protected void execute(Event e) {
|
||||
for (Entity entity : entities.getArray(e)) {
|
||||
if (CraftEngineFurniture.isFurniture(entity)) {
|
||||
Furniture bukkitFurniture = CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity);
|
||||
if (bukkitFurniture != null) {
|
||||
bukkitFurniture.destroy();
|
||||
}
|
||||
Furniture bukkitFurniture = CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity);
|
||||
if (bukkitFurniture != null) {
|
||||
bukkitFurniture.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.event;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.doc.Description;
|
||||
import ch.njol.skript.doc.Name;
|
||||
import ch.njol.skript.doc.Since;
|
||||
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.CraftEngineReloadEvent;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Name("On CraftEngine Reload")
|
||||
@Description({"Fires when CraftEngine reload"})
|
||||
@Since("1.0")
|
||||
public class EvtCraftEngineReload extends SkriptEvent {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEvent("CraftEngine Loaded", EvtCraftEngineReload.class, CraftEngineReloadEvent.class, "(ce|craft(engine|-engine)) [first] (load[ed]|reload)")
|
||||
.description("Called when Craft-Engine resource loaded.");
|
||||
}
|
||||
|
||||
private boolean onlyCheckFirstCall;
|
||||
private static boolean hasBeenCalled = false;
|
||||
|
||||
@Override
|
||||
public boolean init(Literal<?>[] args, int matchedPattern, SkriptParser.ParseResult parser) {
|
||||
// 检查是否包含 "first" 关键词
|
||||
String expr = parser.expr;
|
||||
this.onlyCheckFirstCall = expr.contains("first");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
if (!(event instanceof CraftEngineReloadEvent reloadEvent)) {
|
||||
return false;
|
||||
}
|
||||
if (onlyCheckFirstCall) {
|
||||
if (hasBeenCalled) return false; // 如果 hasBeenCalled 已经为 true,代表已经调用过了, 故返回 false。
|
||||
hasBeenCalled = true;
|
||||
return true;
|
||||
}
|
||||
hasBeenCalled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return onlyCheckFirstCall ? "craftengine first load" : "craftengine reload";
|
||||
}
|
||||
|
||||
public static boolean hasBeenLoad() {
|
||||
return hasBeenCalled;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,48 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.event;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.doc.Description;
|
||||
import ch.njol.skript.doc.Name;
|
||||
import ch.njol.skript.doc.Since;
|
||||
import ch.njol.skript.lang.Literal;
|
||||
import ch.njol.skript.lang.SkriptEvent;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.skript.registrations.EventValues;
|
||||
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.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
@Name("On Custom Block Place And Break")
|
||||
@Description({"Fires when a Custom block gets place and broken"})
|
||||
@Since("1.0")
|
||||
public class EvtCustomBlock extends SkriptEvent {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEvent("Break Custom Block", EvtCustomBlock.class, CustomBlockBreakEvent.class, "(break[ing]|1¦min(e|ing)) [[of] %-unsafeblockstatematchers%]")
|
||||
Skript.registerEvent("Break Custom Block", EvtCustomBlock.class, CustomBlockBreakEvent.class, "(break[ing]|1¦min(e|ing)) of (custom|ce|craft-engine) block[s] [[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, "(plac(e|ing)|build[ing]) [[of] %-unsafeblockstatematchers%]")
|
||||
EventValues.registerEventValue(CustomBlockBreakEvent.class, Location.class, CustomBlockBreakEvent::location, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockBreakEvent.class, Player.class, CustomBlockBreakEvent::getPlayer, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockBreakEvent.class, Block.class, CustomBlockBreakEvent::bukkitBlock, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockBreakEvent.class, World.class, event -> event.location().getWorld(), EventValues.TIME_NOW);
|
||||
|
||||
Skript.registerEvent("Place Custom Block", EvtCustomBlock.class, CustomBlockPlaceEvent.class, "(plac(e|ing)|build[ing]) of (custom|ce|craft-engine) block[s] [[of] %-unsafeblockstatematchers%]")
|
||||
.description("Called when a player places a custom block.");
|
||||
EventValues.registerEventValue(CustomBlockPlaceEvent.class, Location.class, CustomBlockPlaceEvent::location, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockPlaceEvent.class, Player.class, CustomBlockPlaceEvent::player, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockPlaceEvent.class, Block.class, CustomBlockPlaceEvent::bukkitBlock, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockPlaceEvent.class, World.class, event -> event.location().getWorld(), EventValues.TIME_NOW);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -3,20 +3,32 @@ 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.doc.Description;
|
||||
import ch.njol.skript.doc.Name;
|
||||
import ch.njol.skript.doc.Since;
|
||||
import ch.njol.skript.lang.Literal;
|
||||
import ch.njol.skript.lang.SkriptEvent;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.skript.registrations.EventValues;
|
||||
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.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Name("On Click on Custom Block and Furniture")
|
||||
@Description({"Fires when click on custom block and furniture"})
|
||||
@Since("1.0")
|
||||
public class EvtCustomClick extends SkriptEvent {
|
||||
|
||||
private final static int RIGHT = 1, LEFT = 2, ANY = RIGHT | LEFT;
|
||||
@@ -25,8 +37,20 @@ public class EvtCustomClick extends SkriptEvent {
|
||||
@SuppressWarnings("unchecked")
|
||||
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%");
|
||||
"[(" + RIGHT + ":right|" + LEFT + ":left)(| |-)][mouse(| |-)]click[ing] of (ce|craft-engine) [on %-unsafeblockstatematchers/strings%] [(with|using|holding) %-itemtype%]",
|
||||
"[(" + RIGHT + ":right|" + LEFT + ":left)(| |-)][mouse(| |-)]click[ing] of (ce|craft-engine) (with|using|holding) %itemtype% on %unsafeblockstatematchers/strings%");
|
||||
|
||||
EventValues.registerEventValue(CustomBlockInteractEvent.class, Location.class, CustomBlockInteractEvent::location, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockInteractEvent.class, Player.class, CustomBlockInteractEvent::player, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockInteractEvent.class, Block.class, CustomBlockInteractEvent::bukkitBlock, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockInteractEvent.class, Entity.class, event -> null, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockInteractEvent.class, World.class, event -> event.location().getWorld(), EventValues.TIME_NOW);
|
||||
|
||||
EventValues.registerEventValue(FurnitureInteractEvent.class, Location.class, FurnitureInteractEvent::location, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(FurnitureInteractEvent.class, Player.class, FurnitureInteractEvent::player, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(CustomBlockInteractEvent.class, Block.class, event -> null, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(FurnitureInteractEvent.class, Entity.class, event -> event.furniture().baseEntity(), EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(FurnitureInteractEvent.class, World.class, event -> event.location().getWorld(), EventValues.TIME_NOW);
|
||||
}
|
||||
|
||||
private @Nullable Literal<?> type;
|
||||
|
||||
@@ -1,24 +1,44 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.event;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.doc.Description;
|
||||
import ch.njol.skript.doc.Name;
|
||||
import ch.njol.skript.doc.Since;
|
||||
import ch.njol.skript.lang.Literal;
|
||||
import ch.njol.skript.lang.SkriptEvent;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.skript.registrations.EventValues;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurniturePlaceEvent;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
@Name("On Custom Furniture Place And Break")
|
||||
@Description({"Fires when a Custom furniture gets place and broken"})
|
||||
@Since("1.0")
|
||||
public class EvtCustomFurniture extends SkriptEvent {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEvent("Break Furniture", EvtCustomFurniture.class, FurnitureBreakEvent.class, "(break[ing]) [[of] %-strings%]")
|
||||
Skript.registerEvent("Break Furniture", EvtCustomFurniture.class, FurnitureBreakEvent.class, "(break[ing]) of [(custom|ce|craft-engine)] furniture[s] [[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%]")
|
||||
EventValues.registerEventValue(FurnitureBreakEvent.class, Location.class, FurnitureBreakEvent::location, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(FurnitureBreakEvent.class, Player.class, FurnitureBreakEvent::player, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(FurnitureBreakEvent.class, Entity.class, event -> event.furniture().baseEntity(), EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(FurnitureBreakEvent.class, World.class, event -> event.location().getWorld(), EventValues.TIME_NOW);
|
||||
|
||||
Skript.registerEvent("Place Furniture", EvtCustomFurniture.class, FurniturePlaceEvent.class, "(plac(e|ing)|build[ing]) of [(custom|ce|craft-engine)] furniture[s] [[of] %-strings%]")
|
||||
.description("Called when a player places a furniture.");
|
||||
EventValues.registerEventValue(FurniturePlaceEvent.class, Location.class, FurniturePlaceEvent::location, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(FurniturePlaceEvent.class, Player.class, FurniturePlaceEvent::player, EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(FurniturePlaceEvent.class, Entity.class, event -> event.furniture().baseEntity(), EventValues.TIME_NOW);
|
||||
EventValues.registerEventValue(FurniturePlaceEvent.class, World.class, event -> event.location().getWorld(), EventValues.TIME_NOW);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.util.Optional;
|
||||
public class ExprBlockCustomBlockID extends SimplePropertyExpression<Object, String> {
|
||||
|
||||
public static void register() {
|
||||
register(ExprBlockCustomBlockID.class, String.class, "custom block id", "blocks/blockdata/customblockstates");
|
||||
register(ExprBlockCustomBlockID.class, String.class, "(custom|ce|craft-engine) block [namespace] 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, "custom block[ ]state", "blocks/blockdata");
|
||||
register(ExprBlockCustomBlockState.class, ImmutableBlockState.class, "(custom|ce|craft-engine) block[ ]state", "blocks/blockdata");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.aliases.ItemType;
|
||||
import ch.njol.skript.doc.Description;
|
||||
import ch.njol.skript.doc.Name;
|
||||
import ch.njol.skript.doc.Since;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.ExpressionType;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
@@ -14,29 +18,44 @@ import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ExprCustomItem extends SimpleExpression<ItemStack> {
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Name("CraftEngine Item")
|
||||
@Description({"Get CraftEngine items."})
|
||||
@Since("1.0")
|
||||
public class ExprCustomItem extends SimpleExpression<ItemType> {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerExpression(ExprCustomItem.class, ItemStack.class, ExpressionType.SIMPLE, "[(the|a)] custom item [with id] %string%");
|
||||
Skript.registerExpression(ExprCustomItem.class, ItemType.class, ExpressionType.SIMPLE, "[(the|a)] (custom|ce|craft-engine) item [with [namespace] id] %strings%");
|
||||
}
|
||||
|
||||
private Expression<String> itemId;
|
||||
private Expression<?> itemIds;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
itemId = (Expression<String>) exprs[0];
|
||||
itemIds = exprs[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemStack[] get(Event e) {
|
||||
String itemId = this.itemId.getSingle(e);
|
||||
if (itemId == null)
|
||||
return null;
|
||||
CustomItem<ItemStack> customItem = CraftEngineItems.byId(Key.of(itemId));
|
||||
return customItem == null ? null : new ItemStack[] {customItem.buildItemStack(ItemBuildContext.EMPTY)};
|
||||
protected ItemType[] get(Event event) {
|
||||
Object[] objects = itemIds.getArray(event);
|
||||
List<ItemType> items = new ArrayList<>();
|
||||
|
||||
for (Object object : objects) {
|
||||
if (object instanceof String string) {
|
||||
CustomItem<ItemStack> customItem = CraftEngineItems.byId(Key.of(string));
|
||||
if (customItem != null) {
|
||||
ItemType itemType = new ItemType(customItem.buildItemStack(ItemBuildContext.EMPTY));
|
||||
items.add(itemType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items.toArray(new ItemType[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,12 +64,12 @@ public class ExprCustomItem extends SimpleExpression<ItemStack> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ItemStack> getReturnType() {
|
||||
return ItemStack.class;
|
||||
public Class<ItemType> getReturnType() {
|
||||
return ItemType.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event e, boolean debug) {
|
||||
return "the custom item with id " + itemId.toString(e, debug);
|
||||
return "craft-engine item with id " + itemIds.toString(e, debug);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ import java.util.Optional;
|
||||
public class ExprEntityFurnitureID extends SimplePropertyExpression<Object, String> {
|
||||
|
||||
public static void register() {
|
||||
register(ExprEntityFurnitureID.class, String.class, "furniture id", "entities");
|
||||
register(ExprEntityFurnitureID.class, String.class, "[(custom|ce|craft-engine)] furniture [namespace] id", "entities");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String convert(Object object) {
|
||||
if (object instanceof Entity entity && CraftEngineFurniture.isFurniture(entity)) {
|
||||
if (object instanceof Entity entity) {
|
||||
return Optional.ofNullable(CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity))
|
||||
.map(it -> it.id().toString())
|
||||
.orElse(null);
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
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 ch.njol.skript.doc.Description;
|
||||
import ch.njol.skript.doc.Name;
|
||||
import ch.njol.skript.doc.Since;
|
||||
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.skript.util.slot.Slot;
|
||||
import ch.njol.util.Kleenean;
|
||||
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;
|
||||
@@ -14,27 +20,52 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ExprItemCustomItemID extends SimplePropertyExpression<Object, String> {
|
||||
@Name("CraftEngine Item ID")
|
||||
@Description({"Get CraftEngine item id."})
|
||||
@Since("1.0")
|
||||
public class ExprItemCustomItemID extends SimpleExpression<String> {
|
||||
|
||||
public static void register() {
|
||||
register(ExprItemCustomItemID.class, String.class, "custom item id", "itemstacks/itemtypes");
|
||||
Skript.registerExpression(ExprItemCustomItemID.class, String.class, ExpressionType.PROPERTY,
|
||||
"(custom|ce|craft-engine) item [namespace] id of %itemstack/itemtype/slot%",
|
||||
"%itemstack/itemtype/slot%'[s] (custom|ce|craft-engine) item [namespace] id"
|
||||
);
|
||||
}
|
||||
|
||||
private Expression<?> itemStackExpr;
|
||||
|
||||
@Override
|
||||
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
itemStackExpr = exprs[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
@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);
|
||||
protected String[] get(Event event) {
|
||||
Object single = itemStackExpr.getSingle(event);
|
||||
|
||||
String result = null;
|
||||
if (single instanceof ItemStack itemStack) {
|
||||
result = Optional.of(itemStack).map(this::getCraftEngineItemId).orElse(null);
|
||||
} else if (single instanceof ItemType itemType) {
|
||||
result = Optional.ofNullable(itemType.getTypes().getFirst().getStack()).map(this::getCraftEngineItemId).orElse(null);
|
||||
} else if (single instanceof Slot slot) {
|
||||
result = Optional.ofNullable(slot.getItem()).map(this::getCraftEngineItemId).orElse(null);
|
||||
}
|
||||
return null;
|
||||
|
||||
return new String[] {result};
|
||||
}
|
||||
|
||||
|
||||
private String getCraftEngineItemId(ItemStack itemStack) {
|
||||
return Optional.ofNullable(CraftEngineItems.getCustomItemId(itemStack))
|
||||
.map(Key::asString)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyName() {
|
||||
return "custom item id";
|
||||
public boolean isSingle() {
|
||||
return itemStackExpr.isSingle();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,23 +73,14 @@ public class ExprItemCustomItemID extends SimplePropertyExpression<Object, Strin
|
||||
return String.class;
|
||||
}
|
||||
|
||||
// 不需要处理 add, delete 等修改操作
|
||||
@Override
|
||||
public Class<?>[] acceptChange(Changer.ChangeMode mode) {
|
||||
return CollectionUtils.array(String.class);
|
||||
return null;
|
||||
}
|
||||
|
||||
@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);
|
||||
} else if (item instanceof ItemType itemType) {
|
||||
Item<ItemStack> item2 = BukkitItemManager.instance().createWrappedItem(id, null);
|
||||
itemType.setItemMeta(item2.getItem().getItemMeta());
|
||||
}
|
||||
}
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return "craft-engine item ID of " + itemStackExpr.toString(event, debug);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,11 @@ import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.WorldStorageInjector;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.block.EmptyBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.LazyReference;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||
import net.momirealms.craftengine.core.world.SectionPos;
|
||||
@@ -47,38 +48,45 @@ import static java.util.Objects.requireNonNull;
|
||||
public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
private static int[] ordinalToIbdID;
|
||||
private final Set<CEChunk> chunksToSave;
|
||||
private final CEWorld ceWorld;
|
||||
private final LazyReference<CEWorld> ceWorld;
|
||||
private final Set<ChunkPos> brokenChunks = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
protected FastAsyncWorldEditDelegate(EditSessionEvent event, Extent extent) {
|
||||
super(extent);
|
||||
this.chunksToSave = new HashSet<>();
|
||||
World weWorld = event.getWorld();
|
||||
org.bukkit.World world = Bukkit.getWorld(requireNonNull(weWorld).getName());
|
||||
CEWorld ceWorld = CraftEngine.instance().worldManager().getWorld(requireNonNull(world).getUID());
|
||||
this.ceWorld = requireNonNull(ceWorld);
|
||||
this.ceWorld = LazyReference.lazyReference(() -> {
|
||||
World weWorld = event.getWorld();
|
||||
requireNonNull(weWorld, "WorldEdit world is null");
|
||||
org.bukkit.World world = Bukkit.getWorld(weWorld.getName());
|
||||
requireNonNull(world, () -> "WorldEdit world " + weWorld.getName() + " is not a Bukkit world");
|
||||
CEWorld ceWorld = BukkitWorldManager.instance().getWorld(world);
|
||||
requireNonNull(ceWorld, () -> "WorldEdit world " + world.getName() + " is not a CraftEngine world");
|
||||
return ceWorld;
|
||||
});
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
Settings.settings().EXTENT.ALLOWED_PLUGINS.add(FastAsyncWorldEditDelegate.class.getCanonicalName());
|
||||
FaweAdapter<?, ?> adapter = (FaweAdapter<?, ?>) WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
Method ordinalToIbdIDMethod = ReflectionUtils.getDeclaredMethod(CachedBukkitAdapter.class, int.class.arrayType(), new String[]{"getOrdinalToIbdID"});
|
||||
try {
|
||||
assert ordinalToIbdIDMethod != null;
|
||||
ordinalToIbdID = (int[]) ordinalToIbdIDMethod.invoke(adapter);
|
||||
Method ordinalToIbdIDMethod = CachedBukkitAdapter.class.getDeclaredMethod("getOrdinalToIbdID"); // 这样获取有代码提示
|
||||
ordinalToIbdIDMethod.setAccessible(true);
|
||||
if (WorldEditPlugin.getInstance().getBukkitImplAdapter() instanceof FaweAdapter<?, ?> faweAdapter) { // 确保是 paper 服务器的才调用这个
|
||||
ordinalToIbdID = (int[]) ordinalToIbdIDMethod.invoke(faweAdapter);
|
||||
} else { // 应该在 spigot 的服务器上用不了这个
|
||||
CraftEngine.instance().logger().warn("Failed to init FastAsyncWorldEdit compatibility, Please use the server of paper or its fork.");
|
||||
return;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to init FastAsyncWorldEdit compatibility", e);
|
||||
CraftEngine.instance().logger().warn("Failed to init FastAsyncWorldEdit compatibility", e);
|
||||
return;
|
||||
}
|
||||
WorldEdit.getInstance().getEventBus().register(new Object() {
|
||||
@Subscribe
|
||||
@SuppressWarnings("unused")
|
||||
public void onEditSessionEvent(EditSessionEvent event) {
|
||||
World weWorld = event.getWorld();
|
||||
if (weWorld == null) return;
|
||||
Extent currentExtent = event.getExtent();
|
||||
if (event.getStage() == EditSession.Stage.BEFORE_CHANGE) {
|
||||
event.setExtent(new FastAsyncWorldEditDelegate(event, currentExtent));
|
||||
}
|
||||
if (event.getWorld() == null || event.getStage() != EditSession.Stage.BEFORE_CHANGE) return;
|
||||
if (!BukkitWorldManager.instance().initialized()) return;
|
||||
event.setExtent(new FastAsyncWorldEditDelegate(event, event.getExtent()));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -101,6 +109,10 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
}
|
||||
}
|
||||
|
||||
private CEWorld ceWorld() {
|
||||
return this.ceWorld.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBlocks(final Set<BlockVector3> vset, final Pattern pattern) {
|
||||
this.processBlocks(vset, pattern, getMask(), null);
|
||||
@@ -180,10 +192,10 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
Operation operation = super.commit();
|
||||
List<ChunkPos> chunks = new ArrayList<>(this.brokenChunks);
|
||||
this.brokenChunks.clear();
|
||||
Object worldServer = this.ceWorld.world().serverWorld();
|
||||
Object worldServer = this.ceWorld().world().serverWorld();
|
||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(worldServer);
|
||||
for (ChunkPos chunk : chunks) {
|
||||
CEChunk loaded = this.ceWorld.getChunkAtIfLoaded(chunk.longKey());
|
||||
CEChunk loaded = this.ceWorld().getChunkAtIfLoaded(chunk.longKey());
|
||||
// only inject loaded chunks
|
||||
if (loaded == null) continue;
|
||||
injectLevelChunk(chunkSource, loaded);
|
||||
@@ -214,8 +226,8 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
this.brokenChunks.add(ChunkPos.of(chunkX, chunkZ));
|
||||
if (BlockStateUtils.isVanillaBlock(newStateId) && BlockStateUtils.isVanillaBlock(oldStateId)) return;
|
||||
try {
|
||||
CEChunk ceChunk = Optional.ofNullable(this.ceWorld.getChunkAtIfLoaded(chunkX, chunkZ))
|
||||
.orElse(this.ceWorld.worldDataStorage().readChunkAt(this.ceWorld, new ChunkPos(chunkX, chunkZ)));
|
||||
CEChunk ceChunk = Optional.ofNullable(this.ceWorld().getChunkAtIfLoaded(chunkX, chunkZ))
|
||||
.orElse(this.ceWorld().worldDataStorage().readChunkAt(this.ceWorld(), new ChunkPos(chunkX, chunkZ)));
|
||||
CESection ceSection = ceChunk.sectionById(SectionPos.blockToSectionCoord(blockY));
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(newStateId);
|
||||
if (immutableBlockState == null) {
|
||||
@@ -232,7 +244,7 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
private void saveAllChunks() {
|
||||
try {
|
||||
for (CEChunk ceChunk : this.chunksToSave) {
|
||||
this.ceWorld.worldDataStorage().writeChunkAt(ceChunk.chunkPos(), ceChunk);
|
||||
this.ceWorld().worldDataStorage().writeChunkAt(ceChunk.chunkPos(), ceChunk);
|
||||
}
|
||||
this.chunksToSave.clear();
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -56,6 +56,22 @@ public final class CraftEngineBlocks {
|
||||
return place(location, block, UpdateOption.UPDATE_ALL, playSound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Place a custom block
|
||||
*
|
||||
* @param location location
|
||||
* @param blockId block owner id
|
||||
* @param playSound whether to play place sounds
|
||||
* @return success or not
|
||||
*/
|
||||
public static boolean place(@NotNull Location location,
|
||||
@NotNull Key blockId,
|
||||
boolean playSound) {
|
||||
CustomBlock block = byId(blockId);
|
||||
if (block == null) return false;
|
||||
return place(location, block.defaultState(), UpdateOption.UPDATE_ALL, playSound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Place a custom block with given properties
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.block;
|
||||
|
||||
import io.papermc.paper.event.block.BlockBreakBlockEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
@@ -56,7 +57,7 @@ public final class BlockEventListener implements Listener {
|
||||
public void onPlayerAttack(EntityDamageByEntityEvent event) {
|
||||
if (!VersionHelper.isOrAbove1_20_5()) {
|
||||
if (event.getDamager() instanceof Player player) {
|
||||
BukkitServerPlayer serverPlayer = plugin.adapt(player);
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
serverPlayer.setClientSideCanBreakBlock(true);
|
||||
}
|
||||
}
|
||||
@@ -65,7 +66,7 @@ public final class BlockEventListener implements Listener {
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlaceBlock(BlockPlaceEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
BukkitServerPlayer serverPlayer = plugin.adapt(player);
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
// send swing if player is clicking a replaceable block
|
||||
if (serverPlayer.shouldResendSwing()) {
|
||||
player.swingHand(event.getHand());
|
||||
@@ -112,7 +113,7 @@ public final class BlockEventListener implements Listener {
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
Player player = event.getPlayer();
|
||||
Location location = block.getLocation();
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(player.getWorld());
|
||||
WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
@@ -246,7 +247,7 @@ public final class BlockEventListener implements Listener {
|
||||
Location location = player.getLocation();
|
||||
ImmutableBlockState state = optionalCustomState.get();
|
||||
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
|
||||
state.owner().value().execute(PlayerOptionalContext.of(this.plugin.adapt(player), ContextHolder.builder()
|
||||
state.owner().value().execute(PlayerOptionalContext.of(BukkitAdaptors.adapt(player), ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||
.withParameter(DirectContextParameters.POSITION, new WorldPosition(new BukkitWorld(event.getWorld()), LocationUtils.toVec3d(location)))
|
||||
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block))
|
||||
|
||||
@@ -3,8 +3,6 @@ package net.momirealms.craftengine.bukkit.block;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
@@ -26,16 +24,7 @@ import net.momirealms.craftengine.bukkit.util.TagUtils;
|
||||
import net.momirealms.craftengine.core.block.*;
|
||||
import net.momirealms.craftengine.core.block.behavior.EmptyBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.parser.BlockStateParser;
|
||||
import net.momirealms.craftengine.core.block.properties.Properties;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.pack.ResourceLocation;
|
||||
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
||||
import net.momirealms.craftengine.core.plugin.config.StringKeyConstructor;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
@@ -43,10 +32,10 @@ import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.sound.Sounds;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.chunk.PalettedContainer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -68,20 +57,15 @@ import java.util.function.Predicate;
|
||||
public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
private static BukkitBlockManager instance;
|
||||
private final BukkitCraftEngine plugin;
|
||||
private final BlockParser blockParser;
|
||||
|
||||
// The total amount of blocks registered
|
||||
private int customBlockCount;
|
||||
private ImmutableBlockState[] stateId2ImmutableBlockStates;
|
||||
// Minecraft objects
|
||||
// Cached new blocks $ holders
|
||||
private Map<Key, Integer> internalId2StateId;
|
||||
private Map<Key, DelegatingBlock> registeredBlocks;
|
||||
private Map<Integer, Object> stateId2BlockHolder;
|
||||
// This map is used to change the block states that are not necessarily needed into a certain block state
|
||||
private Map<Integer, Integer> blockAppearanceMapper;
|
||||
// Used to automatically arrange block states for strings such as minecraft:note_block:0
|
||||
private Map<Key, List<Integer>> blockAppearanceArranger;
|
||||
private Map<Key, List<Integer>> realBlockArranger;
|
||||
// Record the amount of real blocks by block type
|
||||
private Map<Key, Integer> registeredRealBlockSlots;
|
||||
// A set of blocks that sounds have been removed
|
||||
@@ -102,7 +86,6 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
super(plugin);
|
||||
instance = this;
|
||||
this.plugin = plugin;
|
||||
this.blockParser = new BlockParser();
|
||||
this.initVanillaRegistry();
|
||||
this.loadMappingsAndAdditionalBlocks();
|
||||
this.registerBlocks();
|
||||
@@ -124,6 +107,11 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
this.resetPacketConsumers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stateRegistryIdToStateSNBT(int id) {
|
||||
return BlockStateUtils.idToBlockState(id).toString();
|
||||
}
|
||||
|
||||
public static BukkitBlockManager instance() {
|
||||
return instance;
|
||||
}
|
||||
@@ -227,12 +215,7 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigParser parser() {
|
||||
return this.blockParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBlock(Key id, CustomBlock customBlock) {
|
||||
public void addBlockInternal(Key id, CustomBlock customBlock) {
|
||||
// bind appearance and real state
|
||||
for (ImmutableBlockState state : customBlock.variantProvider().states()) {
|
||||
ImmutableBlockState previous = this.stateId2ImmutableBlockStates[state.customBlockState().registryId() - BlockStateUtils.vanillaStateSize()];
|
||||
@@ -243,7 +226,7 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
this.tempBlockAppearanceConvertor.put(state.customBlockState().registryId(), state.vanillaBlockState().registryId());
|
||||
this.appearanceToRealState.computeIfAbsent(state.vanillaBlockState().registryId(), k -> new IntArrayList()).add(state.customBlockState().registryId());
|
||||
}
|
||||
super.addBlock(id, customBlock);
|
||||
super.addBlockInternal(id, customBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -251,6 +234,11 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
return BlockStateUtils.getBlockOwnerIdFromState(state.handle());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Key getBlockOwnerId(int id) {
|
||||
return BlockStateUtils.getBlockOwnerIdFromState(BlockStateUtils.idToBlockState(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int availableAppearances(Key blockType) {
|
||||
return Optional.ofNullable(this.registeredRealBlockSlots.get(blockType)).orElse(0);
|
||||
@@ -297,6 +285,11 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
BlockStateUtils.init(vanillaStateCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CustomBlock.Builder platformBuilder(Key id) {
|
||||
return BukkitCustomBlock.builder(id);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerBlocks() {
|
||||
this.plugin.logger().info("Registering blocks. Please wait...");
|
||||
@@ -325,7 +318,9 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
this.realBlockArranger = builder3.build();
|
||||
this.registeredBlocks = builder4.build();
|
||||
this.blockRegisterOrder = ImmutableList.copyOf(order);
|
||||
|
||||
if (MCUtils.ceilLog2(BlockStateUtils.vanillaStateSize() + counter) == MCUtils.ceilLog2(BlockStateUtils.vanillaStateSize())) {
|
||||
PalettedContainer.NEED_DOWNGRADE = false;
|
||||
}
|
||||
for (Object block : (Iterable<Object>) MBuiltInRegistries.BLOCK) {
|
||||
Object soundType = CoreReflections.field$BlockBehaviour$soundType.get(block);
|
||||
if (affectedBlockSounds.contains(soundType)) {
|
||||
@@ -401,225 +396,6 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
return cachedUpdateTagsPacket;
|
||||
}
|
||||
|
||||
public class BlockParser implements ConfigParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[]{"blocks", "block"};
|
||||
|
||||
@Override
|
||||
public String[] sectionId() {
|
||||
return CONFIG_SECTION_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int loadingSequence() {
|
||||
return LoadingSequence.BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
if (id.namespace().equals("minecraft") && Registry.MATERIAL.get(KeyUtils.toNamespacedKey(id)) != null) {
|
||||
parseVanillaBlock(pack, path, id, section);
|
||||
} else {
|
||||
// check duplicated config
|
||||
if (BukkitBlockManager.this.byId.containsKey(id)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.duplicate");
|
||||
}
|
||||
parseCustomBlock(pack, path, id, section);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseCustomBlock(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
// read block settings
|
||||
BlockSettings settings = BlockSettings.fromMap(id, MiscUtils.castToMap(section.get("settings"), true));
|
||||
// read states
|
||||
Map<String, Property<?>> properties;
|
||||
Map<String, Integer> appearances;
|
||||
Map<String, BlockStateVariant> variants;
|
||||
|
||||
Map<String, Object> stateSection = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(section, "state", "states"), "warning.config.block.missing_state"), true);
|
||||
boolean singleState = !stateSection.containsKey("properties");
|
||||
// single state
|
||||
if (singleState) {
|
||||
properties = Map.of();
|
||||
int internalId = ResourceConfigUtils.getAsInt(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("id"), "warning.config.block.state.missing_real_id"), "id");
|
||||
VanillaBlockState vanillaBlock = getVanillaBlock(id, stateSection);
|
||||
appearances = Map.of("", vanillaBlock.registryId());
|
||||
Key internalBlockId = Key.of(Key.DEFAULT_NAMESPACE, vanillaBlock.type().value() + "_" + internalId);
|
||||
int internalBlockRegistryId = Optional.ofNullable(internalId2StateId.get(internalBlockId)).orElse(-1);
|
||||
if (internalBlockRegistryId == -1) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_real_id", internalBlockId.toString(), String.valueOf(availableAppearances(vanillaBlock.type()) - 1));
|
||||
}
|
||||
variants = Map.of("", new BlockStateVariant("", settings, internalBlockRegistryId));
|
||||
} else {
|
||||
// properties
|
||||
properties = getProperties(MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("properties"), "warning.config.block.state.missing_properties"), true));
|
||||
// appearance
|
||||
appearances = new HashMap<>();
|
||||
Map<String, Key> appearance2BlockType = new HashMap<>();
|
||||
for (Map.Entry<String, Object> appearanceEntry : MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("appearances"), "warning.config.block.state.missing_appearances"), false).entrySet()) {
|
||||
if (appearanceEntry.getValue() instanceof Map<?, ?>) {
|
||||
VanillaBlockState vanillaBlock = getVanillaBlock(id, MiscUtils.castToMap(appearanceEntry.getValue(), false));
|
||||
appearances.put(appearanceEntry.getKey(), vanillaBlock.registryId());
|
||||
appearance2BlockType.put(appearanceEntry.getKey(), vanillaBlock.type());
|
||||
}
|
||||
}
|
||||
// variants
|
||||
variants = new HashMap<>();
|
||||
for (Map.Entry<String, Object> variantEntry : MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("variants"), "warning.config.block.state.missing_variants"), false).entrySet()) {
|
||||
if (variantEntry.getValue() instanceof Map<?, ?>) {
|
||||
Map<String, Object> variantSection = MiscUtils.castToMap(variantEntry.getValue(), false);
|
||||
String variantNBT = variantEntry.getKey();
|
||||
String appearance = ResourceConfigUtils.requireNonEmptyStringOrThrow(variantSection.get("appearance"), "warning.config.block.state.variant.missing_appearance");
|
||||
if (!appearances.containsKey(appearance)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.variant.invalid_appearance", variantNBT, appearance);
|
||||
}
|
||||
int internalId = ResourceConfigUtils.getAsInt(ResourceConfigUtils.requireNonNullOrThrow(variantSection.get("id"), "warning.config.block.state.missing_real_id"), "id");
|
||||
Key baseBlock = appearance2BlockType.get(appearance);
|
||||
Key internalBlockId = Key.of(Key.DEFAULT_NAMESPACE, baseBlock.value() + "_" + internalId);
|
||||
int internalBlockRegistryId = Optional.ofNullable(internalId2StateId.get(internalBlockId)).orElse(-1);
|
||||
if (internalBlockRegistryId == -1) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_real_id", internalBlockId.toString(), String.valueOf(availableAppearances(baseBlock) - 1));
|
||||
}
|
||||
Map<String, Object> anotherSetting = MiscUtils.castToMap(variantSection.get("settings"), true);
|
||||
variants.put(variantNBT, new BlockStateVariant(appearance, anotherSetting == null ? settings : BlockSettings.ofFullCopy(settings, anotherSetting), internalBlockRegistryId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomBlock block = BukkitCustomBlock.builder(id)
|
||||
.appearances(appearances)
|
||||
.variantMapper(variants)
|
||||
.properties(properties)
|
||||
.settings(settings)
|
||||
.lootTable(LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), true)))
|
||||
.behavior(MiscUtils.getAsMapList(ResourceConfigUtils.get(section, "behavior", "behaviors")))
|
||||
.events(EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")))
|
||||
.build();
|
||||
|
||||
addBlock(id, block);
|
||||
}
|
||||
|
||||
private void parseVanillaBlock(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
Map<String, Object> settings = MiscUtils.castToMap(section.get("settings"), true);
|
||||
if (settings != null) {
|
||||
Object clientBoundTags = settings.get("client-bound-tags");
|
||||
if (clientBoundTags instanceof List<?> list) {
|
||||
List<String> clientSideTags = MiscUtils.getAsStringList(list).stream().filter(ResourceLocation::isValid).toList();
|
||||
Object nmsBlock = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, KeyUtils.toResourceLocation(id));
|
||||
FastNMS.INSTANCE.method$IdMap$getId(MBuiltInRegistries.BLOCK, nmsBlock).ifPresent(i ->
|
||||
BukkitBlockManager.this.clientBoundTags.put(i, clientSideTags));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<String, Property<?>> getProperties(Map<String, Object> propertiesSection) {
|
||||
Map<String, Property<?>> properties = new HashMap<>();
|
||||
for (Map.Entry<String, Object> entry : propertiesSection.entrySet()) {
|
||||
Property<?> property = Properties.fromMap(entry.getKey(), MiscUtils.castToMap(entry.getValue(), false));
|
||||
properties.put(entry.getKey(), property);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private VanillaBlockState getVanillaBlock(Key id, Map<String, Object> section) {
|
||||
// require state non null
|
||||
String vanillaBlockStateTag = ResourceConfigUtils.requireNonEmptyStringOrThrow(section.get("state"), "warning.config.block.state.missing_state");
|
||||
// get its registry id
|
||||
int vanillaBlockStateRegistryId = getVanillaBlockStateRegistryId(vanillaBlockStateTag);
|
||||
// check if another block has occupied the appearance
|
||||
// TODO blocks share the same look
|
||||
Key ifAny = this.tempRegistryIdConflictMap.get(vanillaBlockStateRegistryId);
|
||||
if (ifAny != null && !ifAny.equals(id)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.conflict", BlockStateUtils.fromBlockData(BlockStateUtils.idToBlockState(vanillaBlockStateRegistryId)).getAsString(), ifAny.toString());
|
||||
}
|
||||
// require models not to be null
|
||||
Object models = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(section, "models", "model"), "warning.config.block.state.missing_model");
|
||||
List<JsonObject> variants = ResourceConfigUtils.parseConfigAsList(models, this::getVariantModel);
|
||||
if (variants.isEmpty()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.missing_model");
|
||||
}
|
||||
// TODO blocks share the same look
|
||||
this.tempRegistryIdConflictMap.put(vanillaBlockStateRegistryId, id);
|
||||
// gets the full block state
|
||||
String blockState = BlockStateUtils.idToBlockState(vanillaBlockStateRegistryId).toString();
|
||||
Key blockId = Key.of(blockState.substring(blockState.indexOf('{') + 1, blockState.lastIndexOf('}')));
|
||||
String propertyNBT = blockState.substring(blockState.indexOf('[') + 1, blockState.lastIndexOf(']'));
|
||||
// for generating assets
|
||||
JsonElement combinedVariant = GsonHelper.combine(variants);
|
||||
this.blockStateOverrides.computeIfAbsent(blockId, k -> new HashMap<>()).put(propertyNBT, combinedVariant);
|
||||
this.tempVanillaBlockStateModels.put(vanillaBlockStateRegistryId, combinedVariant);
|
||||
return new VanillaBlockState(blockId, propertyNBT, vanillaBlockStateRegistryId);
|
||||
}
|
||||
|
||||
public record VanillaBlockState(Key type, String properties, int registryId) {
|
||||
}
|
||||
|
||||
private JsonObject getVariantModel(Map<String, Object> singleModelMap) {
|
||||
JsonObject json = new JsonObject();
|
||||
String modelPath = ResourceConfigUtils.requireNonEmptyStringOrThrow(singleModelMap.get("path"), "warning.config.block.state.model.missing_path");
|
||||
if (!ResourceLocation.isValid(modelPath)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.model.invalid_path", modelPath);
|
||||
}
|
||||
json.addProperty("model", modelPath);
|
||||
if (singleModelMap.containsKey("x"))
|
||||
json.addProperty("x", ResourceConfigUtils.getAsInt(singleModelMap.get("x"), "x"));
|
||||
if (singleModelMap.containsKey("y"))
|
||||
json.addProperty("y", ResourceConfigUtils.getAsInt(singleModelMap.get("y"), "y"));
|
||||
if (singleModelMap.containsKey("uvlock")) json.addProperty("uvlock", ResourceConfigUtils.getAsBoolean(singleModelMap.get("uvlock"), "uvlock"));
|
||||
if (singleModelMap.containsKey("weight"))
|
||||
json.addProperty("weight", ResourceConfigUtils.getAsInt(singleModelMap.get("weight"), "weight"));
|
||||
Map<String, Object> generationMap = MiscUtils.castToMap(singleModelMap.get("generation"), true);
|
||||
if (generationMap != null) {
|
||||
prepareModelGeneration(ModelGeneration.of(Key.of(modelPath), generationMap));
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
private int getVanillaBlockStateRegistryId(String blockState) {
|
||||
String[] split = blockState.split(":", 3);
|
||||
if (split.length >= 4) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", blockState);
|
||||
}
|
||||
int registryId;
|
||||
String stateOrId = split[split.length - 1];
|
||||
boolean isId = !stateOrId.contains("[") && !stateOrId.contains("]");
|
||||
if (isId) {
|
||||
if (split.length == 1) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", blockState);
|
||||
}
|
||||
Key block = split.length == 2 ? Key.of(split[0]) : Key.of(split[0], split[1]);
|
||||
try {
|
||||
int id = split.length == 2 ? Integer.parseInt(split[1]) : Integer.parseInt(split[2]);
|
||||
if (id < 0) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", blockState);
|
||||
}
|
||||
List<Integer> arranger = this.blockAppearanceArranger.get(block);
|
||||
if (arranger == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.unavailable_vanilla", blockState);
|
||||
}
|
||||
if (id >= arranger.size()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla_id", blockState, String.valueOf(arranger.size() - 1));
|
||||
}
|
||||
registryId = arranger.get(id);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", e, blockState);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
BlockData blockData = Bukkit.createBlockData(blockState);
|
||||
registryId = BlockStateUtils.blockDataToId(blockData);
|
||||
if (!this.blockAppearanceMapper.containsKey(registryId)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.unavailable_vanilla", blockState);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", e, blockState);
|
||||
}
|
||||
}
|
||||
return registryId;
|
||||
}
|
||||
|
||||
private void loadMappingsAndAdditionalBlocks() {
|
||||
this.plugin.logger().info("Loading mappings.yml.");
|
||||
Path mappingsFile = this.plugin.dataFolderPath().resolve("mappings.yml");
|
||||
@@ -757,13 +533,19 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
}
|
||||
|
||||
private LinkedHashMap<Key, Integer> buildRegisteredRealBlockSlots(Map<Key, Integer> counter, Map<String, Object> additionalYaml) {
|
||||
LinkedHashMap<Key, Integer> map = new LinkedHashMap<>();
|
||||
for (Map.Entry<Key, Integer> entry : counter.entrySet()) {
|
||||
String id = entry.getKey().toString();
|
||||
int additionalStates = (int) additionalYaml.getOrDefault(id, 0);
|
||||
int internalIds = entry.getValue() + additionalStates;
|
||||
plugin.logger().info("Loaded " + id + " with " + entry.getValue() + " appearances and " + internalIds + " real block states");
|
||||
map.put(entry.getKey(), internalIds);
|
||||
LinkedHashMap<Key, Integer> map = new LinkedHashMap<>(counter);
|
||||
for (Map.Entry<String, Object> entry : additionalYaml.entrySet()) {
|
||||
Key blockType = Key.of(entry.getKey());
|
||||
if (entry.getValue() instanceof Integer i) {
|
||||
int previous = map.getOrDefault(blockType, 0);
|
||||
if (previous == 0) {
|
||||
map.put(blockType, i);
|
||||
this.plugin.logger().info("Loaded " + blockType + " with " + i + " real block states");
|
||||
} else {
|
||||
map.put(blockType, i + previous);
|
||||
this.plugin.logger().info("Loaded " + blockType + " with " + previous + " appearances and " + (i + previous) + " real block states");
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
@@ -885,4 +667,21 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getBlockRegistryId(Key id) {
|
||||
Object block = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, KeyUtils.toResourceLocation(id));
|
||||
return FastNMS.INSTANCE.method$IdMap$getId(MBuiltInRegistries.BLOCK, block).orElseThrow(() -> new IllegalStateException("Block " + id + " not found"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVanillaBlock(Key id) {
|
||||
if (!id.namespace().equals("minecraft")) {
|
||||
return false;
|
||||
}
|
||||
if (id.value().equals("air")) {
|
||||
return true;
|
||||
}
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, KeyUtils.toResourceLocation(id)) != MBlocks.AIR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class StackableBlockBehavior extends BukkitBlockBehavior {
|
||||
private void updateStackableBlock(ImmutableBlockState state, BlockPos pos, World world, Item<ItemStack> item, Player player, InteractionHand hand) {
|
||||
ImmutableBlockState nextStage = state.cycle(this.amountProperty);
|
||||
Location location = new Location((org.bukkit.World) world.platformWorld(), pos.x(), pos.y(), pos.z());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world.serverWorld(), LocationUtils.toBlockPos(pos), nextStage.customBlockState().handle(), UpdateOption.UPDATE_NONE.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world.serverWorld(), LocationUtils.toBlockPos(pos), nextStage.customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
if (this.stackSound != null) {
|
||||
world.playBlockSound(new Vec3d(location.getX(), location.getY(), location.getZ()), this.stackSound);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class AbstractMinecartData<T> extends VehicleEntityData<T> {
|
||||
// 1.20~1.21.2
|
||||
public static final AbstractMinecartData<Integer> DisplayBlock = of(AbstractMinecartData.class, EntityDataValue.Serializers$INT, BlockStateUtils.blockStateToId(MBlocks.AIR$defaultState), !VersionHelper.isOrAbove1_21_3());
|
||||
// 1.21.3+
|
||||
public static final AbstractMinecartData<Optional<Object>> CustomDisplayBlock = of(AbstractMinecartData.class, EntityDataValue.Serializers$OPTIONAL_BLOCK_STATE, Optional.empty(), VersionHelper.isOrAbove1_21_3());
|
||||
public static final AbstractMinecartData<Integer> DisplayOffset = of(AbstractMinecartData.class, EntityDataValue.Serializers$INT, 6, true);
|
||||
// 1.20~1.21.2
|
||||
public static final AbstractMinecartData<Boolean> CustomDisplay = of(AbstractMinecartData.class, EntityDataValue.Serializers$BOOLEAN, false, !VersionHelper.isOrAbove1_21_3());
|
||||
|
||||
public static <T> AbstractMinecartData<T> of(final Class<?> clazz, final Object serializer, T defaultValue, boolean condition) {
|
||||
if (!condition) return null;
|
||||
return new AbstractMinecartData<>(clazz, serializer, defaultValue);
|
||||
}
|
||||
|
||||
public AbstractMinecartData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
public class BlockAttachedEntityData<T> extends BaseEntityData<T> {
|
||||
|
||||
public BlockAttachedEntityData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
|
||||
public class BlockDisplayEntityData<T> extends DisplayEntityData<T> {
|
||||
// Block display only
|
||||
public static final DisplayEntityData<Object> DisplayedBlock = new BlockDisplayEntityData<>(BlockDisplayEntityData.class, EntityDataValue.Serializers$BLOCK_STATE, MBlocks.AIR$defaultState);
|
||||
public static final BlockDisplayEntityData<Object> DisplayedBlock = new BlockDisplayEntityData<>(BlockDisplayEntityData.class, EntityDataValue.Serializers$BLOCK_STATE, MBlocks.AIR$defaultState);
|
||||
|
||||
public BlockDisplayEntityData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class EnderManData<T> extends MonsterData<T> {
|
||||
public static final EnderManData<Optional<Object>> CarryState = new EnderManData<>(EnderManData.class, EntityDataValue.Serializers$OPTIONAL_BLOCK_STATE, Optional.empty());
|
||||
public static final EnderManData<Boolean> Creepy = new EnderManData<>(EnderManData.class, EntityDataValue.Serializers$BOOLEAN, false);
|
||||
public static final EnderManData<Boolean> StaredAt = new EnderManData<>(EnderManData.class, EntityDataValue.Serializers$BOOLEAN, false);
|
||||
|
||||
public EnderManData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
public class GlowItemFrameData<T> extends ItemFrameData<T> {
|
||||
|
||||
public GlowItemFrameData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
public class HangingEntityData<T> extends BlockAttachedEntityData<T> {
|
||||
// 1.21.6+
|
||||
public static final HangingEntityData<Object> Direction = of(HangingEntityData.class, EntityDataValue.Serializers$DIRECTION, CoreReflections.instance$Direction$SOUTH, VersionHelper.isOrAbove1_21_6());
|
||||
|
||||
public static <T> HangingEntityData<T> of(final Class<?> clazz, final Object serializer, T defaultValue, boolean condition) {
|
||||
if (!condition) return null;
|
||||
return new HangingEntityData<>(clazz, serializer, defaultValue);
|
||||
}
|
||||
|
||||
public HangingEntityData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
|
||||
|
||||
public class ItemDisplayEntityData<T> extends DisplayEntityData<T> {
|
||||
// Item display only
|
||||
public static final DisplayEntityData<Object> DisplayedItem = new ItemDisplayEntityData<>(ItemDisplayEntityData.class, EntityDataValue.Serializers$ITEM_STACK, CoreReflections.instance$ItemStack$EMPTY);
|
||||
public static final ItemDisplayEntityData<Object> DisplayedItem = new ItemDisplayEntityData<>(ItemDisplayEntityData.class, EntityDataValue.Serializers$ITEM_STACK, CoreReflections.instance$ItemStack$EMPTY);
|
||||
/**
|
||||
* Display type:
|
||||
* 0 = NONE
|
||||
@@ -17,7 +17,7 @@ public class ItemDisplayEntityData<T> extends DisplayEntityData<T> {
|
||||
* 7 = GROUND
|
||||
* 8 = FIXED
|
||||
*/
|
||||
public static final DisplayEntityData<Byte> DisplayType = new ItemDisplayEntityData<>(ItemDisplayEntityData.class, EntityDataValue.Serializers$BYTE, (byte) 0);
|
||||
public static final ItemDisplayEntityData<Byte> DisplayType = new ItemDisplayEntityData<>(ItemDisplayEntityData.class, EntityDataValue.Serializers$BYTE, (byte) 0);
|
||||
|
||||
public ItemDisplayEntityData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
|
||||
public class ItemFrameData<T> extends HangingEntityData<T> {
|
||||
public static final ItemFrameData<Object> Item = new ItemFrameData<>(ItemFrameData.class, EntityDataValue.Serializers$ITEM_STACK, CoreReflections.instance$ItemStack$EMPTY);
|
||||
public static final ItemFrameData<Integer> Rotation = new ItemFrameData<>(ItemFrameData.class, EntityDataValue.Serializers$INT, 0);
|
||||
|
||||
public ItemFrameData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
public class MonsterData<T> extends PathfinderMobData<T> {
|
||||
|
||||
public MonsterData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
public class PrimedTntData<T> extends BaseEntityData<T> {
|
||||
public static final PrimedTntData<Integer> Fuse = of(PrimedTntData.class, EntityDataValue.Serializers$INT, 80, true);
|
||||
// 1.20.3+
|
||||
public static final PrimedTntData<Object> BlockState = of(PrimedTntData.class, EntityDataValue.Serializers$BLOCK_STATE, MBlocks.TNT$defaultState, VersionHelper.isOrAbove1_20_3());
|
||||
|
||||
public static <T> PrimedTntData<T> of(final Class<?> clazz, final Object serializer, T defaultValue, boolean condition) {
|
||||
if (!condition) return null;
|
||||
return new PrimedTntData<>(clazz, serializer, defaultValue);
|
||||
}
|
||||
|
||||
public PrimedTntData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,11 @@ package net.momirealms.craftengine.bukkit.entity.data;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
|
||||
public class TextDisplayEntityData<T> extends DisplayEntityData<T> {
|
||||
public static final DisplayEntityData<Object> Text = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$COMPONENT, CoreReflections.instance$Component$empty);
|
||||
public static final DisplayEntityData<Integer> LineWidth = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$INT, 200);
|
||||
public static final DisplayEntityData<Integer> BackgroundColor = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$INT, 0x40000000);
|
||||
public static final DisplayEntityData<Byte> TextOpacity = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$BYTE, (byte) -1);
|
||||
public static final DisplayEntityData<Byte> TextDisplayMasks = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$BYTE, (byte) 0);
|
||||
public static final TextDisplayEntityData<Object> Text = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$COMPONENT, CoreReflections.instance$Component$empty);
|
||||
public static final TextDisplayEntityData<Integer> LineWidth = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$INT, 200);
|
||||
public static final TextDisplayEntityData<Integer> BackgroundColor = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$INT, 0x40000000);
|
||||
public static final TextDisplayEntityData<Byte> TextOpacity = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$BYTE, (byte) -1);
|
||||
public static final TextDisplayEntityData<Byte> TextDisplayMasks = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$BYTE, (byte) 0);
|
||||
|
||||
public TextDisplayEntityData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
public class VehicleEntityData<T> extends BaseEntityData<T> {
|
||||
public static final VehicleEntityData<Integer> Hurt = new VehicleEntityData<>(VehicleEntityData.class, EntityDataValue.Serializers$INT, 0);
|
||||
public static final VehicleEntityData<Integer> HurtDir = new VehicleEntityData<>(VehicleEntityData.class, EntityDataValue.Serializers$INT, 1);
|
||||
public static final VehicleEntityData<Float> Damage = new VehicleEntityData<>(VehicleEntityData.class, EntityDataValue.Serializers$FLOAT, 0.0F);
|
||||
|
||||
public VehicleEntityData(Class<?> clazz, Object serializer, T defaultValue) {
|
||||
super(clazz, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitBox;
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.handler.FurniturePacketHandler;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
@@ -207,15 +209,16 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
BukkitFurniture furniture = addNewFurniture(display, customFurniture);
|
||||
furniture.initializeColliders();
|
||||
for (Player player : display.getTrackedPlayers()) {
|
||||
this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
|
||||
this.plugin.networkManager().sendPacket(this.plugin.adapt(player), furniture.spawnPacket(player));
|
||||
BukkitAdaptors.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
|
||||
this.plugin.networkManager().sendPacket(BukkitAdaptors.adapt(player), furniture.spawnPacket(player));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BukkitFurniture furniture = addNewFurniture(display, customFurniture);
|
||||
for (Player player : display.getTrackedPlayers()) {
|
||||
this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
|
||||
this.plugin.networkManager().sendPacket(this.plugin.adapt(player), furniture.spawnPacket(player));
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
serverPlayer.entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
|
||||
this.plugin.networkManager().sendPacket(serverPlayer, furniture.spawnPacket(player));
|
||||
}
|
||||
if (preventChange) {
|
||||
this.plugin.scheduler().sync().runLater(furniture::initializeColliders, 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.google.gson.JsonObject;
|
||||
import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent;
|
||||
import io.papermc.paper.event.player.AsyncChatDecorateEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.paper.PaperReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
@@ -143,7 +144,7 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
|
||||
if (renameText == null || renameText.isEmpty()) return;
|
||||
Component itemName = Component.text(renameText);
|
||||
EmojiComponentProcessResult replaceProcessResult = replaceComponentEmoji(itemName, this.plugin.adapt(player), renameText);
|
||||
EmojiComponentProcessResult replaceProcessResult = replaceComponentEmoji(itemName, BukkitAdaptors.adapt(player), renameText);
|
||||
if (replaceProcessResult.changed()) {
|
||||
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(result);
|
||||
wrapped.customNameJson(AdventureHelper.componentToJson(replaceProcessResult.newText()));
|
||||
@@ -160,7 +161,7 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
JsonElement json = ComponentUtils.paperAdventureToJsonElement(lines.get(i));
|
||||
if (json == null) continue;
|
||||
Component line = AdventureHelper.jsonElementToComponent(json);
|
||||
EmojiComponentProcessResult result = replaceComponentEmoji(line, plugin.adapt(player));
|
||||
EmojiComponentProcessResult result = replaceComponentEmoji(line, BukkitAdaptors.adapt(player));
|
||||
if (result.changed()) {
|
||||
try {
|
||||
PaperReflections.method$SignChangeEvent$line.invoke(event, i, ComponentUtils.jsonElementToPaperAdventure(AdventureHelper.componentToJsonElement(result.newText())));
|
||||
@@ -191,7 +192,7 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
for (int i = 0; i < pages.size(); i++) {
|
||||
JsonElement json = ComponentUtils.paperAdventureToJsonElement(pages.get(i));
|
||||
Component page = AdventureHelper.jsonElementToComponent(json);
|
||||
EmojiComponentProcessResult result = replaceComponentEmoji(page, plugin.adapt(player));
|
||||
EmojiComponentProcessResult result = replaceComponentEmoji(page, BukkitAdaptors.adapt(player));
|
||||
if (result.changed()) {
|
||||
changed = true;
|
||||
try {
|
||||
@@ -214,7 +215,7 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
Object originalMessage = PaperReflections.field$AsyncChatDecorateEvent$originalMessage.get(event);
|
||||
String rawJsonMessage = ComponentUtils.paperAdventureToJson(originalMessage);
|
||||
if (Config.allowEmojiChat()) {
|
||||
EmojiTextProcessResult processResult = replaceJsonEmoji(rawJsonMessage, this.plugin.adapt(player));
|
||||
EmojiTextProcessResult processResult = replaceJsonEmoji(rawJsonMessage, BukkitAdaptors.adapt(player));
|
||||
boolean hasChanged = processResult.replaced();
|
||||
if (!player.hasPermission(FontManager.BYPASS_CHAT)) {
|
||||
IllegalCharacterProcessResult result = processIllegalCharacters(processResult.text());
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.core.item.*;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||
import net.momirealms.craftengine.core.item.updater.ItemUpdateConfig;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
@@ -25,8 +26,9 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
List<ItemBehavior> behaviors,
|
||||
List<ItemDataModifier<ItemStack>> modifiers, List<ItemDataModifier<ItemStack>> clientBoundModifiers,
|
||||
ItemSettings settings,
|
||||
Map<EventTrigger, List<Function<PlayerOptionalContext>>> events) {
|
||||
super(isVanillaItem, id, materialKey, clientBoundMaterialKey, behaviors, modifiers, clientBoundModifiers, settings, events);
|
||||
Map<EventTrigger, List<Function<PlayerOptionalContext>>> events,
|
||||
ItemUpdateConfig updater) {
|
||||
super(isVanillaItem, id, materialKey, clientBoundMaterialKey, behaviors, modifiers, clientBoundModifiers, settings, events, updater);
|
||||
this.item = item;
|
||||
this.clientItem = clientItem;
|
||||
}
|
||||
@@ -75,6 +77,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
private final List<ItemDataModifier<ItemStack>> modifiers = new ArrayList<>(4);
|
||||
private final List<ItemDataModifier<ItemStack>> clientBoundModifiers = new ArrayList<>(4);
|
||||
private ItemSettings settings;
|
||||
private ItemUpdateConfig updater;
|
||||
|
||||
public BuilderImpl(Object item, Object clientBoundItem) {
|
||||
this.item = item;
|
||||
@@ -153,12 +156,18 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ItemStack> updater(ItemUpdateConfig updater) {
|
||||
this.updater = updater;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomItem<ItemStack> build() {
|
||||
this.modifiers.addAll(this.settings.modifiers());
|
||||
this.clientBoundModifiers.addAll(this.settings.clientBoundModifiers());
|
||||
return new BukkitCustomItem(this.isVanillaItem, this.id, this.item, this.clientBoundItem, this.itemKey, this.clientBoundItemKey, List.copyOf(this.behaviors),
|
||||
List.copyOf(this.modifiers), List.copyOf(this.clientBoundModifiers), this.settings, this.events);
|
||||
List.copyOf(this.modifiers), List.copyOf(this.clientBoundModifiers), this.settings, this.events, updater);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
instance = this;
|
||||
this.plugin = plugin;
|
||||
this.factory = BukkitItemFactory.create(plugin);
|
||||
this.itemEventListener = new ItemEventListener(plugin);
|
||||
this.itemEventListener = new ItemEventListener(plugin, this);
|
||||
this.debugStickListener = new DebugStickListener(plugin);
|
||||
this.armorEventListener = new ArmorEventListener();
|
||||
this.networkItemHandler = VersionHelper.isOrAbove1_20_5() ? new ModernNetworkItemHandler() : new LegacyNetworkItemHandler();
|
||||
@@ -335,7 +335,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
|
||||
@Override
|
||||
public ItemStack buildCustomItemStack(Key id, Player player) {
|
||||
return Optional.ofNullable(this.customItems.get(id)).map(it -> it.buildItemStack(new ItemBuildContext(player, ContextHolder.EMPTY), 1)).orElse(null);
|
||||
return Optional.ofNullable(this.customItemsById.get(id)).map(it -> it.buildItemStack(new ItemBuildContext(player, ContextHolder.EMPTY), 1)).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -349,12 +349,12 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> createCustomWrappedItem(Key id, Player player) {
|
||||
return Optional.ofNullable(customItems.get(id)).map(it -> it.buildItem(player)).orElse(null);
|
||||
return Optional.ofNullable(customItemsById.get(id)).map(it -> it.buildItem(player)).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> createWrappedItem(Key id, @Nullable Player player) {
|
||||
CustomItem<ItemStack> customItem = this.customItems.get(id);
|
||||
CustomItem<ItemStack> customItem = this.customItemsById.get(id);
|
||||
if (customItem != null) {
|
||||
return customItem.buildItem(player);
|
||||
}
|
||||
@@ -365,9 +365,10 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ItemStack createVanillaItemStack(Key id) {
|
||||
Object item = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, KeyUtils.toResourceLocation(id));
|
||||
if (item == null) {
|
||||
if (item == MItems.AIR && !id.equals(ItemKeys.AIR)) {
|
||||
return null;
|
||||
}
|
||||
return FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(item, 1));
|
||||
|
||||
@@ -12,9 +12,11 @@ import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.item.ItemWrapper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
|
||||
@@ -104,6 +106,18 @@ public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
|
||||
return FastNMS.INSTANCE.method$ItemStack$hasComponent(getLiteralObject(), ensureDataComponentType(type));
|
||||
}
|
||||
|
||||
public boolean hasNonDefaultComponent(Object type) {
|
||||
if (VersionHelper.isOrAbove1_21_4()) {
|
||||
return FastNMS.INSTANCE.method$ItemStack$hasNonDefaultComponent(getLiteralObject(), ensureDataComponentType(type));
|
||||
} else {
|
||||
Object item = FastNMS.INSTANCE.method$ItemStack$getItem(this.getLiteralObject());
|
||||
Object componentMap = FastNMS.INSTANCE.method$Item$components(item);
|
||||
Object componentType = ensureDataComponentType(type);
|
||||
Object defaultComponent = FastNMS.INSTANCE.method$DataComponentMap$get(componentMap, componentType);
|
||||
return !Objects.equals(defaultComponent, getComponentExact(componentType));
|
||||
}
|
||||
}
|
||||
|
||||
public void setComponentExact(Object type, final Object value) {
|
||||
FastNMS.INSTANCE.method$ItemStack$setComponent(this.getLiteralObject(), ensureDataComponentType(type), value);
|
||||
}
|
||||
|
||||
@@ -165,6 +165,11 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasNonDefaultComponent(W item, Object type) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setComponent(W item, Object type, Object value) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
|
||||
@@ -267,6 +267,11 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
return item.hasComponent(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasNonDefaultComponent(ComponentItemWrapper item, Object type) {
|
||||
return item.hasNonDefaultComponent(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeComponent(ComponentItemWrapper item, Object type) {
|
||||
item.removeComponent(type);
|
||||
@@ -346,9 +351,9 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
@Override
|
||||
protected void unbreakable(ComponentItemWrapper item, boolean unbreakable) {
|
||||
if (unbreakable) {
|
||||
item.resetComponent(ComponentTypes.UNBREAKABLE);
|
||||
item.setJavaComponent(ComponentTypes.UNBREAKABLE, Map.of());
|
||||
} else {
|
||||
item.setJavaComponent(ComponentTypes.UNBREAKABLE, true);
|
||||
item.resetComponent(ComponentTypes.UNBREAKABLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.item.listener;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
@@ -49,7 +50,7 @@ public class DebugStickListener implements Listener {
|
||||
Material material = itemInHand.getType();
|
||||
if (material != Material.DEBUG_STICK) return;
|
||||
Player bukkitPlayer = event.getPlayer();
|
||||
BukkitServerPlayer player = this.plugin.adapt(bukkitPlayer);
|
||||
BukkitServerPlayer player = BukkitAdaptors.adapt(bukkitPlayer);
|
||||
if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package net.momirealms.craftengine.bukkit.item.listener;
|
||||
|
||||
import io.papermc.paper.event.block.CompostItemEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockInteractEvent;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitCustomItem;
|
||||
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.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
@@ -16,9 +18,11 @@ import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.item.setting.FoodData;
|
||||
import net.momirealms.craftengine.core.item.updater.ItemUpdateResult;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
@@ -44,13 +48,16 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.enchantment.PrepareItemEnchantEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||
import org.bukkit.inventory.EnchantingInventory;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -60,16 +67,18 @@ import java.util.Optional;
|
||||
|
||||
public class ItemEventListener implements Listener {
|
||||
private final BukkitCraftEngine plugin;
|
||||
private final BukkitItemManager itemManager;
|
||||
|
||||
public ItemEventListener(BukkitCraftEngine plugin) {
|
||||
public ItemEventListener(BukkitCraftEngine plugin, BukkitItemManager itemManager) {
|
||||
this.plugin = plugin;
|
||||
this.itemManager = itemManager;
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onInteractEntity(PlayerInteractEntityEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Entity entity = event.getRightClicked();
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
if (serverPlayer == null) return;
|
||||
|
||||
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
@@ -107,7 +116,7 @@ public class ItemEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
if (serverPlayer == null) return;
|
||||
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
// 如果本tick内主手已被处理,则不处理副手
|
||||
@@ -349,7 +358,7 @@ public class ItemEventListener implements Listener {
|
||||
if (action != Action.RIGHT_CLICK_AIR && action != Action.LEFT_CLICK_AIR)
|
||||
return;
|
||||
Player player = event.getPlayer();
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
if (serverPlayer.isSpectatorMode())
|
||||
return;
|
||||
// Gets the item in hand
|
||||
@@ -411,7 +420,7 @@ public class ItemEventListener implements Listener {
|
||||
}
|
||||
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(this.plugin.adapt(event.getPlayer()), ContextHolder.builder()
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(BukkitAdaptors.adapt(event.getPlayer()), ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.ITEM_IN_HAND, wrapped)
|
||||
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||
.withParameter(DirectContextParameters.HAND, event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND)
|
||||
@@ -425,7 +434,7 @@ public class ItemEventListener implements Listener {
|
||||
if (replacement == null) {
|
||||
event.setReplacement(null);
|
||||
} else {
|
||||
ItemStack replacementItem = this.plugin.itemManager().buildItemStack(replacement, this.plugin.adapt(event.getPlayer()));
|
||||
ItemStack replacementItem = this.plugin.itemManager().buildItemStack(replacement, BukkitAdaptors.adapt(event.getPlayer()));
|
||||
event.setReplacement(replacementItem);
|
||||
}
|
||||
}
|
||||
@@ -516,7 +525,7 @@ public class ItemEventListener implements Listener {
|
||||
if (optionalCustomItem.isEmpty()) return;
|
||||
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();
|
||||
if (customItem.clientItem() == FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject())) return;
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
if (serverPlayer == null) return;
|
||||
this.plugin.scheduler().sync().runDelayed(() -> {
|
||||
Object container = FastNMS.INSTANCE.field$Player$containerMenu(serverPlayer.serverPlayer());
|
||||
@@ -533,4 +542,50 @@ public class ItemEventListener implements Listener {
|
||||
serverPlayer.sendPackets(packets, false);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
关于物品更新器
|
||||
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
|
||||
public void onDropItem(PlayerDropItemEvent event) {
|
||||
if (!Config.triggerUpdateDrop()) return;
|
||||
org.bukkit.entity.Item itemDrop = event.getItemDrop();
|
||||
ItemStack itemStack = itemDrop.getItemStack();
|
||||
Item<ItemStack> wrapped = this.itemManager.wrap(itemStack);
|
||||
ItemUpdateResult result = this.itemManager.updateItem(wrapped, () -> ItemBuildContext.of(BukkitAdaptors.adapt(event.getPlayer())));
|
||||
if (result.updated()) {
|
||||
itemDrop.setItemStack((ItemStack) result.finalItem().getItem());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
|
||||
public void onPickUpItem(EntityPickupItemEvent event) {
|
||||
if (!Config.triggerUpdatePickUp()) return;
|
||||
if (!(event.getEntity() instanceof Player player)) return;
|
||||
org.bukkit.entity.Item itemDrop = event.getItem();
|
||||
ItemStack itemStack = itemDrop.getItemStack();
|
||||
Item<ItemStack> wrapped = this.itemManager.wrap(itemStack);
|
||||
ItemUpdateResult result = this.itemManager.updateItem(wrapped, () -> ItemBuildContext.of(BukkitAdaptors.adapt(player)));
|
||||
if (result.updated()) {
|
||||
itemDrop.setItemStack((ItemStack) result.finalItem().getItem());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
|
||||
public void onInventoryClickItem(InventoryClickEvent event) {
|
||||
if (!Config.triggerUpdateClick()) return;
|
||||
if (!(event.getWhoClicked() instanceof Player player)) return;
|
||||
Inventory clickedInventory = event.getClickedInventory();
|
||||
// 点击自己物品栏里的物品
|
||||
if (clickedInventory == null || clickedInventory != player.getInventory()) return;
|
||||
ItemStack currentItem = event.getCurrentItem();
|
||||
Item<ItemStack> wrapped = this.itemManager.wrap(currentItem);
|
||||
ItemUpdateResult result = this.itemManager.updateItem(wrapped, () -> ItemBuildContext.of(BukkitAdaptors.adapt(player)));
|
||||
if (!result.updated() || !result.replaced()) {
|
||||
return;
|
||||
}
|
||||
event.setCurrentItem((ItemStack) result.finalItem().getItem());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.item.recipe;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.Recipe;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public interface BukkitRecipeConvertor<T extends Recipe<ItemStack>> {
|
||||
|
||||
Runnable convert(Key id, T recipe);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.item.recipe;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.papermc.paper.potion.PotionMix;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
@@ -144,11 +145,11 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
.map(Optional::get)
|
||||
.toList();
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
CoreReflections.field$ShapedRecipe$placementInfo.set(shapedRecipe, null);
|
||||
CoreReflections.methodHandle$ShapedRecipe$placementInfoSetter.invokeExact(shapedRecipe, (Object) null);
|
||||
}
|
||||
List<Object> ingredients = getIngredientsFromShapedRecipe(shapedRecipe);
|
||||
modifyIngredients(ingredients, actualIngredients);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to inject shaped recipe", e);
|
||||
}
|
||||
}
|
||||
@@ -158,16 +159,16 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
List<Object> ingredients = new ArrayList<>();
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
Object pattern = CoreReflections.field$1_20_3$ShapedRecipe$pattern.get(recipe);
|
||||
Object pattern = CoreReflections.methodHandle$1_20_3$ShapedRecipe$patternGetter.invokeExact(recipe);
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
List<Optional<Object>> optionals = (List<Optional<Object>>) CoreReflections.field$ShapedRecipePattern$ingredients1_21_2.get(pattern);
|
||||
List<Optional<Object>> optionals = (List<Optional<Object>>) CoreReflections.methodHandle$ShapedRecipePattern$ingredients1_21_2Getter.invokeExact(pattern);
|
||||
for (Optional<Object> optional : optionals) {
|
||||
optional.ifPresent(ingredients::add);
|
||||
}
|
||||
} else {
|
||||
List<Object> objectList = (List<Object>) CoreReflections.field$ShapedRecipePattern$ingredients1_20_3.get(pattern);
|
||||
List<Object> objectList = (List<Object>) CoreReflections.methodHandle$ShapedRecipePattern$ingredients1_20_3Getter.invokeExact(pattern);
|
||||
for (Object object : objectList) {
|
||||
Object[] values = (Object[]) CoreReflections.field$Ingredient$values.get(object);
|
||||
Object[] values = (Object[]) CoreReflections.methodHandle$Ingredient$valuesGetter.invokeExact(object);
|
||||
// is empty or not
|
||||
if (values.length != 0) {
|
||||
ingredients.add(object);
|
||||
@@ -175,15 +176,15 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<Object> objectList = (List<Object>) CoreReflections.field$1_20_1$ShapedRecipe$recipeItems.get(recipe);
|
||||
List<Object> objectList = (List<Object>) CoreReflections.methodHandle$1_20_1$ShapedRecipe$recipeItemsGetter.invokeExact(recipe);
|
||||
for (Object object : objectList) {
|
||||
Object[] values = (Object[]) CoreReflections.field$Ingredient$values.get(object);
|
||||
Object[] values = (Object[]) CoreReflections.methodHandle$Ingredient$valuesGetter.invokeExact(object);
|
||||
if (values.length != 0) {
|
||||
ingredients.add(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to get ingredients from shaped recipe", e);
|
||||
}
|
||||
return ingredients;
|
||||
@@ -193,12 +194,12 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
try {
|
||||
List<Ingredient<ItemStack>> actualIngredients = recipe.ingredientsInUse();
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
CoreReflections.field$ShapelessRecipe$placementInfo.set(shapelessRecipe, null);
|
||||
CoreReflections.methodHandle$ShapelessRecipe$placementInfoSetter.invokeExact(shapelessRecipe, (Object) null);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> ingredients = (List<Object>) CoreReflections.field$ShapelessRecipe$ingredients.get(shapelessRecipe);
|
||||
List<Object> ingredients = (List<Object>) CoreReflections.methodHandle$ShapelessRecipe$ingredientsGetter.invokeExact(shapelessRecipe);
|
||||
modifyIngredients(ingredients, actualIngredients);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to inject shapeless recipe", e);
|
||||
}
|
||||
}
|
||||
@@ -208,12 +209,12 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
Ingredient<ItemStack> actualIngredient = recipe.ingredient();
|
||||
Object ingredient;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
ingredient = CoreReflections.field$SingleItemRecipe$input.get(cookingRecipe);
|
||||
ingredient = CoreReflections.methodHandle$SingleItemRecipe$inputGetter.invokeExact(cookingRecipe);
|
||||
} else {
|
||||
ingredient = CoreReflections.field$AbstractCookingRecipe$input.get(cookingRecipe);
|
||||
ingredient = CoreReflections.methodHandle$AbstractCookingRecipe$inputGetter.invokeExact(cookingRecipe);
|
||||
}
|
||||
modifyIngredients(List.of(ingredient), List.of(actualIngredient));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to inject cooking recipe", e);
|
||||
}
|
||||
}
|
||||
@@ -235,7 +236,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
return itemStacks;
|
||||
}
|
||||
|
||||
private static void modifyIngredients(List<Object> fakeIngredients, List<Ingredient<ItemStack>> actualIngredients) throws ReflectiveOperationException {
|
||||
private static void modifyIngredients(List<Object> fakeIngredients, List<Ingredient<ItemStack>> actualIngredients) throws Throwable {
|
||||
if (fakeIngredients.size() != actualIngredients.size()) {
|
||||
throw new IllegalArgumentException("Ingredient count mismatch");
|
||||
}
|
||||
@@ -244,15 +245,15 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
Ingredient<ItemStack> actualIngredient = actualIngredients.get(i);
|
||||
List<Object> items = getIngredientLooks(actualIngredient.items());
|
||||
if (VersionHelper.isOrAbove1_21_4()) {
|
||||
CoreReflections.field$Ingredient$itemStacks1_21_4.set(ingredient, new HashSet<>(items));
|
||||
CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (Set<Object>) new ObjectOpenHashSet<>(items));
|
||||
} else if (VersionHelper.isOrAbove1_21_2()) {
|
||||
CoreReflections.field$Ingredient$itemStacks1_21_2.set(ingredient, items);
|
||||
CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (List<Object>) items);
|
||||
} else {
|
||||
Object itemStackArray = Array.newInstance(CoreReflections.clazz$ItemStack, items.size());
|
||||
for (int j = 0; j < items.size(); j++) {
|
||||
Array.set(itemStackArray, j, items.get(j));
|
||||
}
|
||||
CoreReflections.field$Ingredient$itemStacks1_20_1.set(ingredient, itemStackArray);
|
||||
CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (Object) itemStackArray);
|
||||
}
|
||||
MODIFIED_INGREDIENTS.add(ingredient);
|
||||
}
|
||||
@@ -308,9 +309,9 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
try {
|
||||
this.stolenFeatureFlagSet = CoreReflections.field$RecipeManager$featureflagset.get(minecraftRecipeManager());
|
||||
CoreReflections.field$RecipeManager$featureflagset.set(minecraftRecipeManager(), null);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.stolenFeatureFlagSet = CoreReflections.methodHandle$RecipeManager$featureflagsetGetter.invokeExact(minecraftRecipeManager());
|
||||
CoreReflections.methodHandle$RecipeManager$featureflagsetSetter.invokeExact(minecraftRecipeManager(), (Object) null);
|
||||
} catch (Throwable e) {
|
||||
this.plugin.logger().warn("Failed to steal feature flag set", e);
|
||||
}
|
||||
}
|
||||
@@ -398,41 +399,44 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
this.replacedDatapackRecipes.clear();
|
||||
try {
|
||||
this.lastDatapackRecipes = scanResources();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
} catch (Throwable e) {
|
||||
this.plugin.logger().warn("Failed to load datapack recipes", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (Config.disableAllVanillaRecipes()) {
|
||||
this.recipesToUnregister.addAll(this.lastDatapackRecipes.keySet().stream().map(it -> Pair.of(it, false)).toList());
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasDisabledAny = !Config.disabledVanillaRecipes().isEmpty();
|
||||
for (Map.Entry<Key, Recipe<ItemStack>> entry : this.lastDatapackRecipes.entrySet()) {
|
||||
if (hasDisabledAny && Config.disabledVanillaRecipes().contains(entry.getKey())) {
|
||||
this.recipesToUnregister.add(Pair.of(entry.getKey(), false));
|
||||
continue;
|
||||
}
|
||||
markAsDataPackRecipe(entry.getKey());
|
||||
registerInternalRecipe(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<Key, Recipe<ItemStack>> scanResources() throws ReflectiveOperationException {
|
||||
Object fileToIdConverter = CoreReflections.method$FileToIdConverter$json.invoke(null, VersionHelper.isOrAbove1_21() ? "recipe" : "recipes");
|
||||
private Map<Key, Recipe<ItemStack>> scanResources() throws Throwable {
|
||||
Object fileToIdConverter = CoreReflections.methodHandle$FileToIdConverter$json.invokeExact((String) (VersionHelper.isOrAbove1_21() ? "recipe" : "recipes"));
|
||||
Object minecraftServer = FastNMS.INSTANCE.method$MinecraftServer$getServer();
|
||||
Object packRepository = CoreReflections.method$MinecraftServer$getPackRepository.invoke(minecraftServer);
|
||||
List<Object> selected = (List<Object>) CoreReflections.field$PackRepository$selected.get(packRepository);
|
||||
Object packRepository = CoreReflections.methodHandle$MinecraftServer$getPackRepository.invokeExact(minecraftServer);
|
||||
List<Object> selected = (List<Object>) CoreReflections.methodHandle$PackRepository$selectedGetter.invokeExact(packRepository);
|
||||
List<Object> packResources = new ArrayList<>();
|
||||
for (Object pack : selected) {
|
||||
packResources.add(CoreReflections.method$Pack$open.invoke(pack));
|
||||
packResources.add(CoreReflections.methodHandle$Pack$open.invokeExact(pack));
|
||||
}
|
||||
Map<Key, Recipe<ItemStack>> recipes = new HashMap<>();
|
||||
boolean hasDisabledAny = !Config.disabledVanillaRecipes().isEmpty();
|
||||
try (AutoCloseable resourceManager = (AutoCloseable) CoreReflections.constructor$MultiPackResourceManager.newInstance(CoreReflections.instance$PackType$SERVER_DATA, packResources)) {
|
||||
Map<Object, Object> scannedResources = (Map<Object, Object>) CoreReflections.method$FileToIdConverter$listMatchingResources.invoke(fileToIdConverter, resourceManager);
|
||||
|
||||
try (AutoCloseable resourceManager = (AutoCloseable) CoreReflections.methodHandle$MultiPackResourceManagerConstructor.invokeExact(CoreReflections.instance$PackType$SERVER_DATA, packResources)) {
|
||||
Map<Object, Object> scannedResources = (Map<Object, Object>) CoreReflections.methodHandle$FileToIdConverter$listMatchingResources.invokeExact(fileToIdConverter, resourceManager);
|
||||
for (Map.Entry<Object, Object> entry : scannedResources.entrySet()) {
|
||||
Key id = extractKeyFromResourceLocation(entry.getKey().toString());
|
||||
if (Config.disableAllVanillaRecipes()) {
|
||||
this.recipesToUnregister.add(new Pair<>(id, false));
|
||||
continue;
|
||||
}
|
||||
if (hasDisabledAny && Config.disabledVanillaRecipes().contains(id)) {
|
||||
this.recipesToUnregister.add(new Pair<>(id, false));
|
||||
continue;
|
||||
}
|
||||
Reader reader = (Reader) CoreReflections.method$Resource$openAsReader.invoke(entry.getValue());
|
||||
Reader reader = (Reader) CoreReflections.methodHandle$Resource$openAsReader.invokeExact(entry.getValue());
|
||||
JsonObject jsonObject = JsonParser.parseReader(reader).getAsJsonObject();
|
||||
Key serializerType = Key.of(jsonObject.get("type").getAsString());
|
||||
RecipeSerializer<ItemStack, ? extends Recipe<ItemStack>> serializer = (RecipeSerializer<ItemStack, ? extends Recipe<ItemStack>>) BuiltInRegistries.RECIPE_SERIALIZER.getValue(serializerType);
|
||||
@@ -446,7 +450,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
this.plugin.logger().warn("Failed to load data pack recipe " + id + ". Json: " + jsonObject, e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
this.plugin.logger().warn("Unknown error occurred when loading data pack recipes", e);
|
||||
}
|
||||
return recipes;
|
||||
@@ -469,6 +473,9 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
for (Pair<Key, Boolean> pair : this.recipesToUnregister) {
|
||||
unregisterPlatformRecipeMainThread(pair.left(), pair.right());
|
||||
}
|
||||
|
||||
this.recipesToUnregister.clear();
|
||||
|
||||
// 注册新的配方
|
||||
for (Recipe<ItemStack> recipe : this.byId.values()) {
|
||||
try {
|
||||
@@ -480,32 +487,32 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
try {
|
||||
// give flags back on 1.21.2+
|
||||
if (VersionHelper.isOrAbove1_21_2() && this.stolenFeatureFlagSet != null) {
|
||||
CoreReflections.field$RecipeManager$featureflagset.set(minecraftRecipeManager(), this.stolenFeatureFlagSet);
|
||||
CoreReflections.methodHandle$RecipeManager$featureflagsetSetter.invokeExact(minecraftRecipeManager(), (Object) this.stolenFeatureFlagSet);
|
||||
this.stolenFeatureFlagSet = null;
|
||||
}
|
||||
|
||||
// refresh recipes
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
CoreReflections.method$RecipeManager$finalizeRecipeLoading.invoke(minecraftRecipeManager());
|
||||
CoreReflections.methodHandle$RecipeManager$finalizeRecipeLoading.invokeExact(minecraftRecipeManager());
|
||||
}
|
||||
|
||||
// send to players
|
||||
CoreReflections.method$DedicatedPlayerList$reloadRecipes.invoke(CraftBukkitReflections.field$CraftServer$playerList.get(Bukkit.getServer()));
|
||||
CoreReflections.methodHandle$DedicatedPlayerList$reloadRecipes.invokeExact(CraftBukkitReflections.methodHandle$CraftServer$playerListGetter.invokeExact(Bukkit.getServer()));
|
||||
|
||||
// now we need to remove the fake `exact` choices
|
||||
if (VersionHelper.isOrAbove1_21_4()) {
|
||||
for (Object ingredient : MODIFIED_INGREDIENTS) {
|
||||
CoreReflections.field$Ingredient$itemStacks1_21_4.set(ingredient, null);
|
||||
CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (Set<Object>) null);
|
||||
}
|
||||
} else if (VersionHelper.isOrAbove1_21_2()) {
|
||||
for (Object ingredient : MODIFIED_INGREDIENTS) {
|
||||
CoreReflections.field$Ingredient$itemStacks1_21_2.set(ingredient, null);
|
||||
CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (List<Object>) null);
|
||||
}
|
||||
}
|
||||
|
||||
// clear cache
|
||||
MODIFIED_INGREDIENTS.clear();
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
this.plugin.logger().warn("Failed to run delayed recipe tasks", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.item.recipe;
|
||||
|
||||
import com.destroystokyo.paper.event.inventory.PrepareResultEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
@@ -455,7 +456,7 @@ public class RecipeEventListener implements Listener {
|
||||
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
|
||||
if (finalCost >= maxRepairCost && !plugin.adapt(player).canInstabuild()) {
|
||||
if (finalCost >= maxRepairCost && !BukkitAdaptors.adapt(player).canInstabuild()) {
|
||||
hasResult = false;
|
||||
}
|
||||
|
||||
@@ -548,7 +549,7 @@ public class RecipeEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
Item<ItemStack> newItem = customItemOptional.get().buildItem(plugin.adapt(player));
|
||||
Item<ItemStack> newItem = customItemOptional.get().buildItem(BukkitAdaptors.adapt(player));
|
||||
newItem.maxDamage(max);
|
||||
newItem.damage(Math.max(max - finalDurability, 0));
|
||||
inventory.setResult(newItem.getItem());
|
||||
@@ -597,7 +598,7 @@ public class RecipeEventListener implements Listener {
|
||||
CraftingInput<ItemStack> input = getCraftingInput(inventory);
|
||||
if (input == null) return;
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
inventory.setResult(craftingTableRecipe.assemble(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
||||
}
|
||||
|
||||
@@ -650,7 +651,7 @@ public class RecipeEventListener implements Listener {
|
||||
SmithingInput<ItemStack> input = getSmithingInput(inventory);
|
||||
if (smithingTrimRecipe.matches(input)) {
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
ItemStack result = smithingTrimRecipe.assemble(getSmithingInput(inventory), new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY));
|
||||
ItemStack result = smithingTrimRecipe.assemble(getSmithingInput(inventory), new ItemBuildContext(BukkitAdaptors.adapt(player), ContextHolder.EMPTY));
|
||||
event.setResult(result);
|
||||
} else {
|
||||
event.setResult(null);
|
||||
@@ -674,7 +675,7 @@ public class RecipeEventListener implements Listener {
|
||||
SmithingInput<ItemStack> input = getSmithingInput(inventory);
|
||||
if (smithingTransformRecipe.matches(input)) {
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
ItemStack processed = smithingTransformRecipe.assemble(input, new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY));
|
||||
ItemStack processed = smithingTransformRecipe.assemble(input, new ItemBuildContext(BukkitAdaptors.adapt(player), ContextHolder.EMPTY));
|
||||
event.setResult(processed);
|
||||
} else {
|
||||
event.setResult(null);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.loot;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
@@ -72,7 +73,7 @@ public class BukkitVanillaLootManager extends AbstractVanillaLootManager impleme
|
||||
BukkitServerPlayer optionalPlayer = null;
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
if (event.getDamageSource().getCausingEntity() instanceof Player player) {
|
||||
optionalPlayer = this.plugin.adapt(player);
|
||||
optionalPlayer = BukkitAdaptors.adapt(player);
|
||||
builder.withParameter(DirectContextParameters.PLAYER, optionalPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.pack;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.api.event.AsyncResourcePackGenerateEvent;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.feature.ReloadCommand;
|
||||
@@ -43,7 +44,7 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
if (Config.sendPackOnJoin() && !VersionHelper.isOrAbove1_20_2()) {
|
||||
Player player = plugin.adapt(event.getPlayer());
|
||||
Player player = BukkitAdaptors.adapt(event.getPlayer());
|
||||
this.sendResourcePack(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
@@ -58,7 +59,6 @@ import java.net.URLConnection;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class BukkitCraftEngine extends CraftEngine {
|
||||
@@ -123,7 +123,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
@Override
|
||||
public void onPluginLoad() {
|
||||
if (super.blockManager == null) {
|
||||
injectRegistries();
|
||||
this.injectRegistries();
|
||||
}
|
||||
try {
|
||||
WorldStorageInjector.init();
|
||||
@@ -363,11 +363,9 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
}
|
||||
}
|
||||
|
||||
public BukkitServerPlayer adapt(org.bukkit.entity.Player player) {
|
||||
if (player == null) return null;
|
||||
return Optional.ofNullable((BukkitServerPlayer) networkManager().getOnlineUser(player)).orElseGet(
|
||||
() -> (BukkitServerPlayer) networkManager().getUser(player)
|
||||
);
|
||||
public BukkitServerPlayer adapt(@NotNull org.bukkit.entity.Player player) {
|
||||
Objects.requireNonNull(player, "player cannot be null");
|
||||
return (BukkitServerPlayer) networkManager().getOnlineUser(player);
|
||||
}
|
||||
|
||||
public AntiGriefLib antiGriefProvider() {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.util.PlayerUtils;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import net.momirealms.craftengine.core.plugin.command.FlagKeys;
|
||||
@@ -47,12 +50,18 @@ public class GetItemCommand extends BukkitCommandFeature<CommandSender> {
|
||||
int amount = context.getOrDefault("amount", 1);
|
||||
boolean toInv = context.flags().hasFlag(FlagKeys.TO_INVENTORY);
|
||||
NamespacedKey namespacedKey = context.get("id");
|
||||
Key key = Key.of(namespacedKey.namespace(), namespacedKey.value());
|
||||
ItemStack builtItem = plugin().itemManager().buildCustomItemStack(key, plugin().adapt(context.sender()));
|
||||
if (builtItem == null) {
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GET_FAILURE_NOT_EXIST, Component.text(key.toString()));
|
||||
return;
|
||||
Key itemId = Key.of(namespacedKey.namespace(), namespacedKey.value());
|
||||
CustomItem<ItemStack> customItem = CraftEngineItems.byId(itemId);
|
||||
if (customItem == null) {
|
||||
customItem = BukkitItemManager.instance().getCustomItemByPathOnly(itemId.value()).orElse(null);
|
||||
if (customItem == null) {
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GET_FAILURE_NOT_EXIST, Component.text(itemId.toString()));
|
||||
return;
|
||||
} else {
|
||||
itemId = customItem.id();
|
||||
}
|
||||
}
|
||||
ItemStack builtItem = customItem.buildItemStack(plugin().adapt(context.sender()));
|
||||
int amountToGive = amount;
|
||||
int maxStack = builtItem.getMaxStackSize();
|
||||
while (amountToGive > 0) {
|
||||
@@ -66,7 +75,7 @@ public class GetItemCommand extends BukkitCommandFeature<CommandSender> {
|
||||
PlayerUtils.dropItem(player, more, false, true, false);
|
||||
}
|
||||
}
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GET_SUCCESS, Component.text(amount), Component.text(key.toString()));
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GET_SUCCESS, Component.text(amount), Component.text(itemId.toString()));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.util.PlayerUtils;
|
||||
@@ -27,7 +28,6 @@ import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class GiveItemCommand extends BukkitCommandFeature<CommandSender> {
|
||||
@@ -54,16 +54,20 @@ public class GiveItemCommand extends BukkitCommandFeature<CommandSender> {
|
||||
int amount = context.getOrDefault("amount", 1);
|
||||
boolean toInv = context.flags().hasFlag(FlagKeys.TO_INVENTORY);
|
||||
NamespacedKey namespacedKey = context.get("id");
|
||||
Key key = Key.of(namespacedKey.namespace(), namespacedKey.value());
|
||||
Optional<CustomItem<ItemStack>> optionalItem = BukkitItemManager.instance().getCustomItem(key);
|
||||
if (optionalItem.isEmpty()) {
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GIVE_FAILURE_NOT_EXIST, Component.text(key.toString()));
|
||||
return;
|
||||
Key itemId = Key.of(namespacedKey.namespace(), namespacedKey.value());
|
||||
CustomItem<ItemStack> customItem = CraftEngineItems.byId(itemId);
|
||||
if (customItem == null) {
|
||||
customItem = BukkitItemManager.instance().getCustomItemByPathOnly(itemId.value()).orElse(null);
|
||||
if (customItem == null) {
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GIVE_FAILURE_NOT_EXIST, Component.text(itemId.toString()));
|
||||
return;
|
||||
} else {
|
||||
itemId = customItem.id();
|
||||
}
|
||||
}
|
||||
|
||||
Collection<Player> players = selector.values();
|
||||
for (Player player : players) {
|
||||
ItemStack builtItem = optionalItem.get().buildItemStack(plugin().adapt(player));
|
||||
ItemStack builtItem = customItem.buildItemStack(plugin().adapt(player));
|
||||
if (builtItem == null) {
|
||||
return;
|
||||
}
|
||||
@@ -90,9 +94,9 @@ public class GiveItemCommand extends BukkitCommandFeature<CommandSender> {
|
||||
}
|
||||
}
|
||||
if (players.size() == 1) {
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GIVE_SUCCESS_SINGLE, Component.text(amount), Component.text(key.toString()), Component.text(players.iterator().next().getName()));
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GIVE_SUCCESS_SINGLE, Component.text(amount), Component.text(itemId.toString()), Component.text(players.iterator().next().getName()));
|
||||
} else if (players.size() > 1) {
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GIVE_SUCCESS_MULTIPLE, Component.text(amount), Component.text(key.toString()), Component.text(players.size()));
|
||||
handleFeedback(context, MessageConstants.COMMAND_ITEM_GIVE_SUCCESS_MULTIPLE, Component.text(amount), Component.text(itemId.toString()), Component.text(players.size()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.BukkitNetworkManager;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.parser.standard.IntegerParser;
|
||||
|
||||
public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
@@ -17,10 +20,22 @@ public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.required("start", IntegerParser.integerParser(0))
|
||||
.senderType(Player.class)
|
||||
.handler(context -> {
|
||||
Player player = context.sender();
|
||||
player.sendMessage("客户端模组状态: " + BukkitNetworkManager.instance().getUser(player).clientModEnabled());
|
||||
Player sender = context.sender();
|
||||
int start = context.get("start");
|
||||
int x = sender.getChunk().getX() * 16;
|
||||
int z = sender.getChunk().getZ() * 16;
|
||||
int y = (sender.getLocation().getBlockY() / 16) * 16;
|
||||
for (int a = 0; a < 16; a++) {
|
||||
for (int b = 0; b < 16; b++) {
|
||||
for (int c = 0; c < 16; c++) {
|
||||
BlockData blockData = BlockStateUtils.fromBlockData(BlockStateUtils.idToBlockState(start + a + b * 16 + c * 256));
|
||||
sender.getWorld().setBlockData(new Location(sender.getWorld(), x + a, y + b, z + c), blockData);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.plugin.gui;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
@@ -91,6 +92,9 @@ public class BukkitGuiManager implements GuiManager, Listener {
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
org.bukkit.inventory.Inventory inventory = event.getInventory();
|
||||
if (!CraftBukkitReflections.clazz$MinecraftInventory.isInstance(FastNMS.INSTANCE.method$CraftInventory$getInventory(inventory))) {
|
||||
return;
|
||||
}
|
||||
if (!(inventory.getHolder() instanceof CraftEngineInventoryHolder craftEngineInventoryHolder)) {
|
||||
return;
|
||||
}
|
||||
@@ -106,6 +110,9 @@ public class BukkitGuiManager implements GuiManager, Listener {
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
|
||||
public void onInventoryDrag(InventoryDragEvent event) {
|
||||
org.bukkit.inventory.Inventory inventory = event.getInventory();
|
||||
if (!CraftBukkitReflections.clazz$MinecraftInventory.isInstance(FastNMS.INSTANCE.method$CraftInventory$getInventory(inventory))) {
|
||||
return;
|
||||
}
|
||||
if (!(inventory.getHolder() instanceof CraftEngineInventoryHolder)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,6 @@ public final class WorldStorageInjector {
|
||||
return section;
|
||||
}
|
||||
|
||||
|
||||
public static class SetBlockStateInterceptor {
|
||||
public static final SetBlockStateInterceptor INSTANCE = new SetBlockStateInterceptor();
|
||||
|
||||
@@ -215,7 +214,7 @@ public final class WorldStorageInjector {
|
||||
}
|
||||
}
|
||||
|
||||
protected static void compareAndUpdateBlockState(int x, int y, int z, Object newState, Object previousState, InjectedHolder holder) {
|
||||
private static void compareAndUpdateBlockState(int x, int y, int z, Object newState, Object previousState, InjectedHolder holder) {
|
||||
try {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(newState);
|
||||
CESection section = holder.ceSection();
|
||||
|
||||
@@ -12,9 +12,11 @@ import net.momirealms.craftengine.bukkit.plugin.network.id.PacketIdFinder;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.id.PacketIds1_20;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.id.PacketIds1_20_5;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.LeavesReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.LibraryReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.FakeBukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.CooldownData;
|
||||
@@ -142,6 +144,47 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to init server connection", e);
|
||||
}
|
||||
// Inject Leaves bot list
|
||||
if (VersionHelper.isLeaves()) {
|
||||
this.injectLeavesBotList();
|
||||
}
|
||||
}
|
||||
|
||||
public static BukkitNetworkManager instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void addFakePlayer(Player player) {
|
||||
FakeBukkitServerPlayer fakePlayer = new FakeBukkitServerPlayer(this.plugin);
|
||||
fakePlayer.setPlayer(player);
|
||||
this.onlineUsers.put(player.getUniqueId(), fakePlayer);
|
||||
this.resetUserArray();
|
||||
}
|
||||
|
||||
public boolean removeFakePlayer(Player player) {
|
||||
BukkitServerPlayer fakePlayer = this.onlineUsers.get(player.getUniqueId());
|
||||
if (!(fakePlayer instanceof FakeBukkitServerPlayer)) {
|
||||
return false;
|
||||
}
|
||||
this.onlineUsers.remove(player.getUniqueId());
|
||||
this.resetUserArray();
|
||||
this.saveCooldown(player, fakePlayer.cooldown());
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void injectLeavesBotList() {
|
||||
try {
|
||||
Object botList = LeavesReflections.field$BotList$INSTANCE.get(null);
|
||||
List<Object> bots = (List<Object>) LeavesReflections.field$BotList$bots.get(botList);
|
||||
ListMonitor<Object> monitor = new ListMonitor<>(bots,
|
||||
(bot) -> addFakePlayer(FastNMS.INSTANCE.method$ServerPlayer$getBukkitEntity(bot)),
|
||||
(bot) -> removeFakePlayer(FastNMS.INSTANCE.method$ServerPlayer$getBukkitEntity(bot))
|
||||
);
|
||||
LeavesReflections.field$BotList$bots.set(botList, monitor);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().severe("Failed to inject leaves bot list");
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPacketHandlers() {
|
||||
@@ -203,10 +246,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerC2SByteBufPacketConsumer(PacketConsumers.INTERACT_ENTITY, this.packetIds.serverboundInteractPacket());
|
||||
}
|
||||
|
||||
public static BukkitNetworkManager instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
@@ -215,10 +254,10 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
user.setPlayer(player);
|
||||
this.onlineUsers.put(player.getUniqueId(), user);
|
||||
this.resetUserArray();
|
||||
// folia在此tick每个玩家
|
||||
if (VersionHelper.isFolia()) {
|
||||
player.getScheduler().runAtFixedRate(plugin.javaPlugin(), (t) -> user.tick(),
|
||||
() -> {
|
||||
}, 1, 1);
|
||||
() -> {}, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +321,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetWorkUser getUser(Channel channel) {
|
||||
public NetWorkUser getUser(@NotNull Channel channel) {
|
||||
ChannelPipeline pipeline = channel.pipeline();
|
||||
return this.users.get(pipeline);
|
||||
}
|
||||
@@ -298,14 +337,18 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
return getChannel((Player) player.platformPlayer());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public NetWorkUser getUser(Player player) {
|
||||
return getUser(getChannel(player));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public NetWorkUser getOnlineUser(Player player) {
|
||||
return this.onlineUsers.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
// 当假人的时候channel为null
|
||||
@NotNull
|
||||
public Channel getChannel(Player player) {
|
||||
return FastNMS.INSTANCE.field$Connection$channel(
|
||||
FastNMS.INSTANCE.field$ServerGamePacketListenerImpl$connection(
|
||||
@@ -318,6 +361,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
|
||||
@Override
|
||||
public void sendPacket(@NotNull NetWorkUser player, Object packet, boolean immediately, Runnable sendListener) {
|
||||
if (player.isFakePlayer()) return;
|
||||
if (immediately) {
|
||||
this.immediatePacketConsumer.accept(player.nettyChannel(), packet, sendListener);
|
||||
} else {
|
||||
@@ -327,6 +371,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
|
||||
@Override
|
||||
public void sendPackets(@NotNull NetWorkUser player, List<Object> packet, boolean immediately, Runnable sendListener) {
|
||||
if (player.isFakePlayer()) return;
|
||||
if (immediately) {
|
||||
this.immediatePacketsConsumer.accept(player.nettyChannel(), packet, sendListener);
|
||||
} else {
|
||||
|
||||
@@ -18,6 +18,7 @@ import net.momirealms.craftengine.bukkit.api.event.FurnitureAttemptBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager;
|
||||
@@ -86,9 +87,10 @@ import java.util.function.BiConsumer;
|
||||
|
||||
public class PacketConsumers {
|
||||
private static BukkitNetworkManager.Handlers[] ADD_ENTITY_HANDLERS;
|
||||
private static int[] mappings;
|
||||
private static int[] mappingsMOD;
|
||||
private static IntIdentityList BLOCK_LIST;
|
||||
private static int[] BLOCK_STATE_MAPPINGS;
|
||||
private static int[] MOD_BLOCK_STATE_MAPPINGS;
|
||||
private static IntIdentityList SERVER_BLOCK_LIST;
|
||||
private static IntIdentityList CLIENT_BLOCK_LIST;
|
||||
private static IntIdentityList BIOME_LIST;
|
||||
|
||||
public static void initEntities(int registrySize) {
|
||||
@@ -137,6 +139,14 @@ public class PacketConsumers {
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.ITEM$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.ITEM_FRAME$registryId] = simpleAddEntityHandler(ItemFramePacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.GLOW_ITEM_FRAME$registryId] = simpleAddEntityHandler(ItemFramePacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.ENDERMAN$registryId] = simpleAddEntityHandler(EndermanPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.CHEST_MINECART$registryId] = simpleAddEntityHandler(AbstractMinecartPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.COMMAND_BLOCK_MINECART$registryId] = simpleAddEntityHandler(AbstractMinecartPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.FURNACE_MINECART$registryId] = simpleAddEntityHandler(AbstractMinecartPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.HOPPER_MINECART$registryId] = simpleAddEntityHandler(AbstractMinecartPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.MINECART$registryId] = simpleAddEntityHandler(AbstractMinecartPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.SPAWNER_MINECART$registryId] = simpleAddEntityHandler(AbstractMinecartPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.TNT_MINECART$registryId] = simpleAddEntityHandler(AbstractMinecartPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.FIREBALL$registryId] = createOptionalCustomProjectileEntityHandler(true);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.EYE_OF_ENDER$registryId] = createOptionalCustomProjectileEntityHandler(true);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.FIREWORK_ROCKET$registryId] = createOptionalCustomProjectileEntityHandler(true);
|
||||
@@ -149,6 +159,9 @@ public class PacketConsumers {
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.TRIDENT$registryId] = createOptionalCustomProjectileEntityHandler(false);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.ARROW$registryId] = createOptionalCustomProjectileEntityHandler(false);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.SPECTRAL_ARROW$registryId] = createOptionalCustomProjectileEntityHandler(false);
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.TNT$registryId] = simpleAddEntityHandler(PrimedTNTPacketHandler.INSTANCE);
|
||||
}
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.OMINOUS_ITEM_SPAWNER$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
||||
}
|
||||
@@ -215,32 +228,35 @@ public class PacketConsumers {
|
||||
}
|
||||
|
||||
public static void initBlocks(Map<Integer, Integer> map, int registrySize) {
|
||||
mappings = new int[registrySize];
|
||||
int[] newMappings = new int[registrySize];
|
||||
for (int i = 0; i < registrySize; i++) {
|
||||
mappings[i] = i;
|
||||
newMappings[i] = i;
|
||||
}
|
||||
mappingsMOD = Arrays.copyOf(mappings, registrySize);
|
||||
int[] newMappingsMOD = Arrays.copyOf(newMappings, registrySize);
|
||||
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
|
||||
mappings[entry.getKey()] = entry.getValue();
|
||||
newMappings[entry.getKey()] = entry.getValue();
|
||||
if (BlockStateUtils.isVanillaBlock(entry.getKey())) {
|
||||
mappingsMOD[entry.getKey()] = entry.getValue();
|
||||
newMappingsMOD[entry.getKey()] = entry.getValue();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < mappingsMOD.length; i++) {
|
||||
for (int i = 0; i < newMappingsMOD.length; i++) {
|
||||
if (BlockStateUtils.isVanillaBlock(i)) {
|
||||
mappingsMOD[i] = remap(i);
|
||||
newMappingsMOD[i] = newMappings[i];
|
||||
}
|
||||
}
|
||||
BLOCK_LIST = new IntIdentityList(registrySize);
|
||||
BLOCK_STATE_MAPPINGS = newMappings;
|
||||
MOD_BLOCK_STATE_MAPPINGS = newMappingsMOD;
|
||||
SERVER_BLOCK_LIST = new IntIdentityList(registrySize);
|
||||
CLIENT_BLOCK_LIST = new IntIdentityList(BlockStateUtils.vanillaStateSize());
|
||||
BIOME_LIST = new IntIdentityList(RegistryUtils.currentBiomeRegistrySize());
|
||||
}
|
||||
|
||||
public static int remap(int stateId) {
|
||||
return mappings[stateId];
|
||||
return BLOCK_STATE_MAPPINGS[stateId];
|
||||
}
|
||||
|
||||
public static int remapMOD(int stateId) {
|
||||
return mappingsMOD[stateId];
|
||||
return MOD_BLOCK_STATE_MAPPINGS[stateId];
|
||||
}
|
||||
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> LEVEL_CHUNK_WITH_LIGHT = (user, event) -> {
|
||||
@@ -292,26 +308,22 @@ public class PacketConsumers {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf);
|
||||
FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
for (int i = 0, count = player.clientSideSectionCount(); i < count; i++) {
|
||||
try {
|
||||
MCSection mcSection = new MCSection(BLOCK_LIST, BIOME_LIST);
|
||||
mcSection.readPacket(friendlyByteBuf);
|
||||
PalettedContainer<Integer> container = mcSection.blockStateContainer();
|
||||
Palette<Integer> palette = container.data().palette();
|
||||
if (palette.canRemap()) {
|
||||
palette.remap(PacketConsumers::remapMOD);
|
||||
} else {
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int state = container.get(j);
|
||||
int newState = remapMOD(state);
|
||||
if (newState != state) {
|
||||
container.set(j, newState);
|
||||
}
|
||||
MCSection mcSection = new MCSection(SERVER_BLOCK_LIST, SERVER_BLOCK_LIST, BIOME_LIST);
|
||||
mcSection.readPacket(friendlyByteBuf);
|
||||
PalettedContainer<Integer> container = mcSection.blockStateContainer();
|
||||
Palette<Integer> palette = container.data().palette();
|
||||
if (palette.canRemap()) {
|
||||
palette.remap(PacketConsumers::remapMOD);
|
||||
} else {
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int state = container.get(j);
|
||||
int newState = remapMOD(state);
|
||||
if (newState != state) {
|
||||
container.set(j, newState);
|
||||
}
|
||||
}
|
||||
mcSection.writePacket(newBuf);
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
mcSection.writePacket(newBuf);
|
||||
}
|
||||
buffer = newBuf.array();
|
||||
} else {
|
||||
@@ -319,26 +331,22 @@ public class PacketConsumers {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf);
|
||||
FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
for (int i = 0, count = player.clientSideSectionCount(); i < count; i++) {
|
||||
try {
|
||||
MCSection mcSection = new MCSection(BLOCK_LIST, BIOME_LIST);
|
||||
mcSection.readPacket(friendlyByteBuf);
|
||||
PalettedContainer<Integer> container = mcSection.blockStateContainer();
|
||||
Palette<Integer> palette = container.data().palette();
|
||||
if (palette.canRemap()) {
|
||||
palette.remap(PacketConsumers::remap);
|
||||
} else {
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int state = container.get(j);
|
||||
int newState = remap(state);
|
||||
if (newState != state) {
|
||||
container.set(j, newState);
|
||||
}
|
||||
MCSection mcSection = new MCSection(CLIENT_BLOCK_LIST, SERVER_BLOCK_LIST, BIOME_LIST);
|
||||
mcSection.readPacket(friendlyByteBuf);
|
||||
PalettedContainer<Integer> container = mcSection.blockStateContainer();
|
||||
Palette<Integer> palette = container.data().palette();
|
||||
if (palette.canRemap()) {
|
||||
palette.remap(PacketConsumers::remap);
|
||||
} else {
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int state = container.get(j);
|
||||
int newState = remap(state);
|
||||
if (newState != state) {
|
||||
container.set(j, newState);
|
||||
}
|
||||
}
|
||||
mcSection.writePacket(newBuf);
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
mcSection.writePacket(newBuf);
|
||||
}
|
||||
buffer = newBuf.array();
|
||||
}
|
||||
@@ -1945,7 +1953,7 @@ public class PacketConsumers {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId != EntityDataUtils.CUSTOM_NAME_DATA_ID) continue;
|
||||
if (entityDataId != BaseEntityData.CustomName.id()) continue;
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isEmpty()) continue;
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
@@ -2241,7 +2249,7 @@ public class PacketConsumers {
|
||||
// 因为不能走编码器只能替换对象
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> CONTAINER_CLICK_1_21_5 = (user, event, packet) -> {
|
||||
try {
|
||||
var player = (net.momirealms.craftengine.core.entity.player.Player) user;
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
int containerId = FastNMS.INSTANCE.field$ServerboundContainerClickPacket$containerId(packet);
|
||||
int stateId = FastNMS.INSTANCE.field$ServerboundContainerClickPacket$stateId(packet);
|
||||
short slotNum = FastNMS.INSTANCE.field$ServerboundContainerClickPacket$slotNum(packet);
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.AbstractMinecartData;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class AbstractMinecartPacketHandler implements EntityPacketHandler {
|
||||
public static final AbstractMinecartPacketHandler INSTANCE = new AbstractMinecartPacketHandler();
|
||||
private static final BlockStateHandler HANDLER = VersionHelper.isOrAbove1_21_3() ? BlockStateHandler_1_21_3.INSTANCE : BlockStateHandler_1_20.INSTANCE;
|
||||
|
||||
@Override
|
||||
public void handleSetEntityData(NetWorkUser user, ByteBufPacketEvent event) {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int id = buf.readVarInt();
|
||||
boolean isChanged = false;
|
||||
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
Object blockState = HANDLER.handle(user, packedItem, entityDataId);
|
||||
if (blockState != null) {
|
||||
packedItems.set(i, blockState);
|
||||
isChanged = true;
|
||||
} else if (Config.interceptEntityName() && entityDataId == BaseEntityData.CustomName.id()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isEmpty()) continue;
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (tokens.isEmpty()) continue;
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
|
||||
entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))
|
||||
));
|
||||
isChanged = true;
|
||||
}
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(id);
|
||||
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
|
||||
}
|
||||
}
|
||||
|
||||
interface BlockStateHandler {
|
||||
Object handle(NetWorkUser user, Object packedItem, int entityDataId);
|
||||
}
|
||||
|
||||
static class BlockStateHandler_1_21_3 implements BlockStateHandler {
|
||||
protected static final BlockStateHandler INSTANCE = new BlockStateHandler_1_21_3();
|
||||
|
||||
@Override
|
||||
public Object handle(NetWorkUser user, Object packedItem, int entityDataId) {
|
||||
if (entityDataId != AbstractMinecartData.CustomDisplayBlock.id()) return null;
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> blockState = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (blockState.isEmpty()) return null;
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState.get());
|
||||
int newStateId;
|
||||
if (!user.clientModEnabled()) {
|
||||
newStateId = PacketConsumers.remap(stateId);
|
||||
} else {
|
||||
newStateId = PacketConsumers.remapMOD(stateId);
|
||||
}
|
||||
if (newStateId == stateId) return null;
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
return FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
|
||||
entityDataId, serializer, Optional.of(BlockStateUtils.idToBlockState(newStateId))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static class BlockStateHandler_1_20 implements BlockStateHandler {
|
||||
protected static final BlockStateHandler INSTANCE = new BlockStateHandler_1_20();
|
||||
|
||||
@Override
|
||||
public Object handle(NetWorkUser user, Object packedItem, int entityDataId) {
|
||||
if (entityDataId != AbstractMinecartData.DisplayBlock.id()) return null;
|
||||
int stateId = (int) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
int newStateId;
|
||||
if (!user.clientModEnabled()) {
|
||||
newStateId = PacketConsumers.remap(stateId);
|
||||
} else {
|
||||
newStateId = PacketConsumers.remapMOD(stateId);
|
||||
}
|
||||
if (newStateId == stateId) return null;
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
return FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, newStateId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
@@ -32,7 +32,7 @@ public class ArmorStandPacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId != EntityDataUtils.CUSTOM_NAME_DATA_ID) continue;
|
||||
if (entityDataId != BaseEntityData.CustomName.id()) continue;
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isEmpty()) continue;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.BlockDisplayEntityData;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
@@ -30,7 +31,7 @@ public class BlockDisplayPacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId == EntityDataUtils.BLOCK_STATE_DATA_ID) {
|
||||
if (entityDataId == BlockDisplayEntityData.DisplayedBlock.id()) {
|
||||
Object blockState = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
int newStateId;
|
||||
@@ -39,12 +40,13 @@ public class BlockDisplayPacketHandler implements EntityPacketHandler {
|
||||
} else {
|
||||
newStateId = PacketConsumers.remapMOD(stateId);
|
||||
}
|
||||
if (newStateId == stateId) continue;
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
|
||||
entityDataId, serializer, BlockStateUtils.idToBlockState(newStateId)
|
||||
));
|
||||
isChanged = true;
|
||||
} else if (Config.interceptEntityName() && entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) {
|
||||
} else if (Config.interceptEntityName() && entityDataId == BaseEntityData.CustomName.id()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isEmpty()) continue;
|
||||
|
||||
@@ -28,7 +28,7 @@ public class CommonItemPacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId != EntityDataUtils.ITEM_DATA_ID) continue;
|
||||
if (entityDataId != EntityDataUtils.UNSAFE_ITEM_DATA_ID) continue;
|
||||
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) {
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.EnderManData;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class EndermanPacketHandler implements EntityPacketHandler {
|
||||
public static final EndermanPacketHandler INSTANCE = new EndermanPacketHandler();
|
||||
|
||||
@Override
|
||||
public void handleSetEntityData(NetWorkUser user, ByteBufPacketEvent event) {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int id = buf.readVarInt();
|
||||
boolean isChanged = false;
|
||||
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId == EnderManData.CarryState.id()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> blockState = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (blockState.isEmpty()) continue;
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState.get());
|
||||
int newStateId;
|
||||
if (!user.clientModEnabled()) {
|
||||
newStateId = PacketConsumers.remap(stateId);
|
||||
} else {
|
||||
newStateId = PacketConsumers.remapMOD(stateId);
|
||||
}
|
||||
if (newStateId == stateId) continue;
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
|
||||
entityDataId, serializer, Optional.of(BlockStateUtils.idToBlockState(newStateId))
|
||||
));
|
||||
isChanged = true;
|
||||
} else if (Config.interceptEntityName() && entityDataId == BaseEntityData.CustomName.id()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isEmpty()) continue;
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (tokens.isEmpty()) continue;
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
|
||||
entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))
|
||||
));
|
||||
isChanged = true;
|
||||
}
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(id);
|
||||
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
@@ -25,7 +25,7 @@ public class ItemDisplayPacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId != EntityDataUtils.DISPLAYED_ITEM_DATA_ID) continue;
|
||||
if (entityDataId != ItemDisplayEntityData.DisplayedItem.id()) continue;
|
||||
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
|
||||
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.data.ItemFrameData;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||
@@ -28,7 +28,7 @@ public class ItemFramePacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId != EntityDataUtils.ITEM_FRAME_DATA_ID) continue;
|
||||
if (entityDataId != ItemFrameData.Item.id()) continue;
|
||||
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) {
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.PrimedTntData;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class PrimedTNTPacketHandler implements EntityPacketHandler {
|
||||
public static final PrimedTNTPacketHandler INSTANCE = new PrimedTNTPacketHandler();
|
||||
|
||||
@Override
|
||||
public void handleSetEntityData(NetWorkUser user, ByteBufPacketEvent event) {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int id = buf.readVarInt();
|
||||
boolean isChanged = false;
|
||||
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId == PrimedTntData.BlockState.id()) {
|
||||
Object blockState = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
int newStateId;
|
||||
if (!user.clientModEnabled()) {
|
||||
newStateId = PacketConsumers.remap(stateId);
|
||||
} else {
|
||||
newStateId = PacketConsumers.remapMOD(stateId);
|
||||
}
|
||||
if (newStateId == stateId) continue;
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
|
||||
entityDataId, serializer, BlockStateUtils.idToBlockState(newStateId)
|
||||
));
|
||||
isChanged = true;
|
||||
} else if (Config.interceptEntityName() && entityDataId == BaseEntityData.CustomName.id()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isEmpty()) continue;
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (tokens.isEmpty()) continue;
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
|
||||
entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))
|
||||
));
|
||||
isChanged = true;
|
||||
}
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(id);
|
||||
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.TextDisplayEntityData;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
@@ -31,7 +31,7 @@ public class TextDisplayPacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId != EntityDataUtils.TEXT_DATA_ID) continue;
|
||||
if (entityDataId != TextDisplayEntityData.Text.id()) continue;
|
||||
Object textComponent = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (textComponent == CoreReflections.instance$Component$empty) break;
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.bukkit;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
@@ -12,6 +14,8 @@ import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.inventory.*;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -201,6 +205,17 @@ public final class CraftBukkitReflections {
|
||||
ReflectionUtils.getDeclaredField(clazz$CraftServer, CoreReflections.clazz$DedicatedPlayerList, 0)
|
||||
);
|
||||
|
||||
public static final MethodHandle methodHandle$CraftServer$playerListGetter;
|
||||
|
||||
static {
|
||||
try {
|
||||
methodHandle$CraftServer$playerListGetter = ReflectionUtils.unreflectGetter(field$CraftServer$playerList)
|
||||
.asType(MethodType.methodType(Object.class, Server.class));
|
||||
} catch (Exception e) {
|
||||
throw new ReflectionInitException("Failed to initialize methodHandle$CraftServer$playerList", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$CraftInventoryCrafting = requireNonNull(
|
||||
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleCBClass("inventory.CraftInventoryCrafting"))
|
||||
);
|
||||
@@ -353,4 +368,8 @@ public final class CraftBukkitReflections {
|
||||
public static final Method method$Level$getCraftWorld = requireNonNull(
|
||||
ReflectionUtils.getMethod(CoreReflections.clazz$Level, clazz$CraftWorld)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$MinecraftInventory = requireNonNull(
|
||||
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleCBClass("inventory.CraftInventoryCustom$MinecraftInventory"))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.VarHandle;
|
||||
@@ -97,6 +98,17 @@ public final class CoreReflections {
|
||||
public static final Method method$FileToIdConverter$json = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(clazz$FileToIdConverter, clazz$FileToIdConverter, String.class)
|
||||
);
|
||||
|
||||
public static final MethodHandle methodHandle$FileToIdConverter$json;
|
||||
|
||||
static {
|
||||
try {
|
||||
methodHandle$FileToIdConverter$json = ReflectionUtils.unreflectMethod(method$FileToIdConverter$json)
|
||||
.asType(MethodType.methodType(Object.class, String.class));
|
||||
} catch (Throwable t) {
|
||||
throw new ReflectionInitException("Failed to initialize methodHandle$FileToIdConverter$json", t);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$RegistryOps = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
@@ -1900,17 +1912,42 @@ public final class CoreReflections {
|
||||
)
|
||||
);
|
||||
|
||||
// 1.20.1-1.21.1
|
||||
public static final Field field$Ingredient$itemStacks1_20_1 =
|
||||
ReflectionUtils.getDeclaredField(clazz$Ingredient, clazz$ItemStack.arrayType(), 0);
|
||||
public static final Field field$Ingredient$itemStacks = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$Ingredient,
|
||||
VersionHelper.isOrAbove1_21_4() ? Set.class : VersionHelper.isOrAbove1_21_2() ? List.class : clazz$ItemStack.arrayType(),
|
||||
VersionHelper.isOrAbove1_21_4() ? 0 : VersionHelper.isOrAbove1_21_2() ? 1 : 0
|
||||
)
|
||||
);
|
||||
|
||||
// 1.21.2-1.21.3
|
||||
public static final Field field$Ingredient$itemStacks1_21_2 =
|
||||
ReflectionUtils.getDeclaredField(clazz$Ingredient, List.class, 1);
|
||||
public static final MethodHandle methodHandle$RecipeManager$finalizeRecipeLoading;
|
||||
public static final MethodHandle methodHandle$RecipeManager$featureflagsetGetter;
|
||||
public static final MethodHandle methodHandle$RecipeManager$featureflagsetSetter;
|
||||
public static final MethodHandle methodHandle$Ingredient$itemStacksSetter;
|
||||
|
||||
// 1.21.4 paper
|
||||
public static final Field field$Ingredient$itemStacks1_21_4 =
|
||||
ReflectionUtils.getDeclaredField(clazz$Ingredient, Set.class, 0);
|
||||
static {
|
||||
try {
|
||||
if (method$RecipeManager$finalizeRecipeLoading != null) {
|
||||
methodHandle$RecipeManager$finalizeRecipeLoading = ReflectionUtils.unreflectMethod(method$RecipeManager$finalizeRecipeLoading)
|
||||
.asType(MethodType.methodType(void.class, Object.class));
|
||||
} else {
|
||||
methodHandle$RecipeManager$finalizeRecipeLoading = null;
|
||||
}
|
||||
if (field$RecipeManager$featureflagset != null) {
|
||||
methodHandle$RecipeManager$featureflagsetGetter = ReflectionUtils.unreflectGetter(field$RecipeManager$featureflagset)
|
||||
.asType(MethodType.methodType(Object.class, Object.class));
|
||||
methodHandle$RecipeManager$featureflagsetSetter = ReflectionUtils.unreflectSetter(field$RecipeManager$featureflagset)
|
||||
.asType(MethodType.methodType(void.class, Object.class, Object.class));
|
||||
} else {
|
||||
methodHandle$RecipeManager$featureflagsetGetter = null;
|
||||
methodHandle$RecipeManager$featureflagsetSetter = null;
|
||||
}
|
||||
methodHandle$Ingredient$itemStacksSetter = ReflectionUtils.unreflectSetter(field$Ingredient$itemStacks)
|
||||
.asType(MethodType.methodType(void.class, Object.class, VersionHelper.isOrAbove1_21_4() ? Set.class : VersionHelper.isOrAbove1_21_2() ? List.class : Object.class));
|
||||
} catch (Exception e) {
|
||||
throw new ReflectionInitException("Failed to initialize CoreReflections", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Since 1.21.2, exact has been removed
|
||||
public static final Field field$Ingredient$exact =
|
||||
@@ -1928,7 +1965,7 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("world.item.crafting.ShapedRecipePattern"));
|
||||
|
||||
// 1.20.1-1.20.2
|
||||
public static final Field field$1_20_1$ShapedRecipe$recipeItems=
|
||||
public static final Field field$1_20_1$ShapedRecipe$recipeItems =
|
||||
ReflectionUtils.getDeclaredField(clazz$ShapedRecipe, clazz$NonNullList, 0);
|
||||
|
||||
// 1.20.3+
|
||||
@@ -1992,6 +2029,70 @@ public final class CoreReflections {
|
||||
Optional.ofNullable(ReflectionUtils.getDeclaredField(clazz$ShapelessRecipe, List.class, 0))
|
||||
.orElse(ReflectionUtils.getDeclaredField(clazz$ShapelessRecipe, clazz$NonNullList, 0));
|
||||
|
||||
public static final MethodHandle methodHandle$1_20_1$ShapedRecipe$recipeItemsGetter;
|
||||
public static final MethodHandle methodHandle$1_20_3$ShapedRecipe$patternGetter;
|
||||
public static final MethodHandle methodHandle$ShapedRecipePattern$ingredients1_20_3Getter;
|
||||
public static final MethodHandle methodHandle$ShapedRecipePattern$ingredients1_21_2Getter;
|
||||
public static final MethodHandle methodHandle$Ingredient$valuesGetter;
|
||||
public static final MethodHandle methodHandle$ShapelessRecipe$placementInfoSetter;
|
||||
public static final MethodHandle methodHandle$ShapedRecipe$placementInfoSetter;
|
||||
public static final MethodHandle methodHandle$ShapelessRecipe$ingredientsGetter;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (field$1_20_1$ShapedRecipe$recipeItems != null) {
|
||||
methodHandle$1_20_1$ShapedRecipe$recipeItemsGetter = ReflectionUtils.unreflectGetter(field$1_20_1$ShapedRecipe$recipeItems)
|
||||
.asType(MethodType.methodType(List.class, Object.class));
|
||||
} else {
|
||||
methodHandle$1_20_1$ShapedRecipe$recipeItemsGetter = null;
|
||||
}
|
||||
if (field$1_20_3$ShapedRecipe$pattern != null) {
|
||||
methodHandle$1_20_3$ShapedRecipe$patternGetter = ReflectionUtils.unreflectGetter(field$1_20_3$ShapedRecipe$pattern)
|
||||
.asType(MethodType.methodType(Object.class, Object.class));
|
||||
} else {
|
||||
methodHandle$1_20_3$ShapedRecipe$patternGetter = null;
|
||||
}
|
||||
if (field$ShapedRecipePattern$ingredients1_20_3 != null) {
|
||||
methodHandle$ShapedRecipePattern$ingredients1_20_3Getter = ReflectionUtils.unreflectGetter(field$ShapedRecipePattern$ingredients1_20_3)
|
||||
.asType(MethodType.methodType(List.class, Object.class));
|
||||
} else {
|
||||
methodHandle$ShapedRecipePattern$ingredients1_20_3Getter = null;
|
||||
}
|
||||
if (field$ShapedRecipePattern$ingredients1_21_2 != null) {
|
||||
methodHandle$ShapedRecipePattern$ingredients1_21_2Getter = ReflectionUtils.unreflectGetter(field$ShapedRecipePattern$ingredients1_21_2)
|
||||
.asType(MethodType.methodType(List.class, Object.class));
|
||||
} else {
|
||||
methodHandle$ShapedRecipePattern$ingredients1_21_2Getter = null;
|
||||
}
|
||||
if (field$Ingredient$values != null) {
|
||||
methodHandle$Ingredient$valuesGetter = ReflectionUtils.unreflectGetter(field$Ingredient$values)
|
||||
.asType(MethodType.methodType(Object[].class, Object.class));
|
||||
} else {
|
||||
methodHandle$Ingredient$valuesGetter = null;
|
||||
}
|
||||
if (field$ShapelessRecipe$placementInfo != null) {
|
||||
methodHandle$ShapelessRecipe$placementInfoSetter = ReflectionUtils.unreflectSetter(field$ShapelessRecipe$placementInfo)
|
||||
.asType(MethodType.methodType(void.class, Object.class, Object.class));
|
||||
} else {
|
||||
methodHandle$ShapelessRecipe$placementInfoSetter = null;
|
||||
}
|
||||
if (field$ShapedRecipe$placementInfo != null) {
|
||||
methodHandle$ShapedRecipe$placementInfoSetter = ReflectionUtils.unreflectSetter(field$ShapedRecipe$placementInfo)
|
||||
.asType(MethodType.methodType(void.class, Object.class, Object.class));
|
||||
} else {
|
||||
methodHandle$ShapedRecipe$placementInfoSetter = null;
|
||||
}
|
||||
if (field$ShapelessRecipe$ingredients != null) {
|
||||
methodHandle$ShapelessRecipe$ingredientsGetter = ReflectionUtils.unreflectGetter(field$ShapelessRecipe$ingredients)
|
||||
.asType(MethodType.methodType(List.class, Object.class));
|
||||
} else {
|
||||
methodHandle$ShapelessRecipe$ingredientsGetter = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ReflectionInitException("Failed to initialize CoreReflections", e);
|
||||
}
|
||||
}
|
||||
|
||||
// require ResourceLocation for 1.20.1-1.21.1
|
||||
// require ResourceKey for 1.21.2+
|
||||
public static final Method method$RecipeManager$byKey;
|
||||
@@ -2093,6 +2194,28 @@ public final class CoreReflections {
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, clazz$Ingredient, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final MethodHandle methodHandle$AbstractCookingRecipe$inputGetter;
|
||||
public static final MethodHandle methodHandle$SingleItemRecipe$inputGetter;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (field$AbstractCookingRecipe$input != null) {
|
||||
methodHandle$AbstractCookingRecipe$inputGetter = ReflectionUtils.unreflectGetter(field$AbstractCookingRecipe$input)
|
||||
.asType(MethodType.methodType(Object.class, Object.class));
|
||||
} else {
|
||||
methodHandle$AbstractCookingRecipe$inputGetter = null;
|
||||
}
|
||||
if (field$SingleItemRecipe$input != null) {
|
||||
methodHandle$SingleItemRecipe$inputGetter = ReflectionUtils.unreflectGetter(field$SingleItemRecipe$input)
|
||||
.asType(MethodType.methodType(Object.class, Object.class));
|
||||
} else {
|
||||
methodHandle$SingleItemRecipe$inputGetter = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ReflectionInitException("Failed to initialize methodHandle$SingleItemRecipe$inputGetter", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Field field$AbstractFurnaceBlockEntity$quickCheck = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$AbstractFurnaceBlockEntity, clazz$RecipeManager$CachedCheck, 0)
|
||||
);
|
||||
@@ -3019,6 +3142,17 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getMethod(clazz$Resource, BufferedReader.class)
|
||||
);
|
||||
|
||||
public static final MethodHandle methodHandle$Resource$openAsReader;
|
||||
|
||||
static {
|
||||
try {
|
||||
methodHandle$Resource$openAsReader = ReflectionUtils.unreflectMethod(method$Resource$openAsReader)
|
||||
.asType(MethodType.methodType(Reader.class, Object.class));
|
||||
} catch (Exception e) {
|
||||
throw new ReflectionInitException("Failed to init methodHandle$Resource$openAsReader", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$MultiPackResourceManager = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"server.packs.resources.ResourceManager",
|
||||
@@ -3063,6 +3197,20 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getInstanceDeclaredField(clazz$PackRepository, List.class, 0)
|
||||
);
|
||||
|
||||
public static final MethodHandle methodHandle$MinecraftServer$getPackRepository;
|
||||
public static final MethodHandle methodHandle$PackRepository$selectedGetter;
|
||||
|
||||
static {
|
||||
try {
|
||||
methodHandle$MinecraftServer$getPackRepository = ReflectionUtils.unreflectMethod(method$MinecraftServer$getPackRepository)
|
||||
.asType(MethodType.methodType(Object.class, Object.class));
|
||||
methodHandle$PackRepository$selectedGetter = ReflectionUtils.unreflectGetter(field$PackRepository$selected)
|
||||
.asType(MethodType.methodType(List.class, Object.class));
|
||||
} catch (Exception e) {
|
||||
throw new ReflectionInitException("Failed to initialize reflection for methodHandle$MinecraftServer$getPackRepository", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$Pack = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"server.packs.repository.ResourcePackLoader",
|
||||
@@ -3109,6 +3257,23 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getMethod(clazz$DedicatedPlayerList, new String[] {"reloadRecipeData", "reloadRecipes"})
|
||||
);
|
||||
|
||||
public static final MethodHandle methodHandle$DedicatedPlayerList$reloadRecipes;
|
||||
public static final MethodHandle methodHandle$Pack$open;
|
||||
public static final MethodHandle methodHandle$MultiPackResourceManagerConstructor;
|
||||
|
||||
static {
|
||||
try {
|
||||
methodHandle$DedicatedPlayerList$reloadRecipes = ReflectionUtils.unreflectMethod(method$DedicatedPlayerList$reloadRecipes)
|
||||
.asType(MethodType.methodType(void.class, Object.class));
|
||||
methodHandle$Pack$open = ReflectionUtils.unreflectMethod(method$Pack$open)
|
||||
.asType(MethodType.methodType(Object.class, Object.class));
|
||||
methodHandle$MultiPackResourceManagerConstructor = ReflectionUtils.unreflectConstructor(constructor$MultiPackResourceManager)
|
||||
.asType(MethodType.methodType(AutoCloseable.class, Object.class, List.class));
|
||||
} catch (Exception e) {
|
||||
throw new ReflectionInitException("Failed to init methodHandle$DedicatedPlayerList$reloadRecipes", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$ServerChunkCache$getGenerator = requireNonNull(
|
||||
ReflectionUtils.getMethod(clazz$ServerChunkCache, clazz$ChunkGenerator)
|
||||
);
|
||||
@@ -3315,6 +3480,17 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getMethod(clazz$FileToIdConverter, Map.class, new String[]{"listMatchingResources", "a"}, clazz$ResourceManager)
|
||||
);
|
||||
|
||||
public static final MethodHandle methodHandle$FileToIdConverter$listMatchingResources;
|
||||
|
||||
static {
|
||||
try {
|
||||
methodHandle$FileToIdConverter$listMatchingResources = ReflectionUtils.unreflectMethod(method$FileToIdConverter$listMatchingResources)
|
||||
.asType(MethodType.methodType(Map.class, Object.class, AutoCloseable.class));
|
||||
} catch (Exception e) {
|
||||
throw new ReflectionInitException("Failed to initialize methodHandle$FileToIdConverter$listMatchingResources", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$RegistryOps$create = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(clazz$RegistryOps, clazz$RegistryOps, DynamicOps.class, clazz$HolderLookup$Provider)
|
||||
);
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
//import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
//import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
//import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
//import org.bukkit.event.HandlerList;
|
||||
//
|
||||
//import java.lang.reflect.Field;
|
||||
//import java.util.Optional;
|
||||
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
// TODO API 太新了需要1.21.8,目前先采用其他方式解决假人问题
|
||||
public final class LeavesReflections {
|
||||
private LeavesReflections() {}
|
||||
|
||||
// public static final Class<?> clazz$BotJoinEvent = MiscUtils.requireNonNullIf(ReflectionUtils.getClazz("org.leavesmc.leaves.event.bot.BotJoinEvent"), VersionHelper.isLeaves());
|
||||
//
|
||||
// public static final Class<?> clazz$BotRemoveEvent = MiscUtils.requireNonNullIf(ReflectionUtils.getClazz("org.leavesmc.leaves.event.bot.BotRemoveEvent"), VersionHelper.isLeaves());
|
||||
//
|
||||
// public static final Class<?> clazz$BotEvent = MiscUtils.requireNonNullIf(ReflectionUtils.getClazz("org.leavesmc.leaves.event.bot.BotEvent"), VersionHelper.isLeaves());
|
||||
//
|
||||
// public static final Class<?> clazz$Bot = MiscUtils.requireNonNullIf(ReflectionUtils.getClazz("org.leavesmc.leaves.entity.bot.Bot"), VersionHelper.isLeaves());
|
||||
//
|
||||
// public static final Field field$BotEvent$bot = Optional.ofNullable(clazz$BotEvent)
|
||||
// .map(it -> ReflectionUtils.getDeclaredField(it, clazz$Bot, 0))
|
||||
// .orElse(null);
|
||||
//
|
||||
// public static final Field field$BotJoinEvent$handlers = Optional.ofNullable(clazz$BotJoinEvent)
|
||||
// .map(it -> ReflectionUtils.getDeclaredField(it, HandlerList.class, 0))
|
||||
// .orElse(null);
|
||||
//
|
||||
// public static final Field field$BotRemoveEvent$handlers = Optional.ofNullable(clazz$BotRemoveEvent)
|
||||
// .map(it -> ReflectionUtils.getDeclaredField(it, HandlerList.class, 0))
|
||||
// .orElse(null);
|
||||
|
||||
|
||||
public static final Class<?> clazz$ServerBot = ReflectionUtils.getClazz("org.leavesmc.leaves.bot.ServerBot");
|
||||
|
||||
// 注入BotList来实现全版本的监听
|
||||
public static final Class<?> clazz$BotList = ReflectionUtils.getClazz("org.leavesmc.leaves.bot.BotList");
|
||||
|
||||
public static final Field field$BotList$INSTANCE = ReflectionUtils.getDeclaredField(clazz$BotList, clazz$BotList, 0);
|
||||
|
||||
public static final Field field$BotList$bots = ReflectionUtils.getDeclaredField(clazz$BotList, List.class, 0);
|
||||
}
|
||||
@@ -20,6 +20,8 @@ public final class MBlocks {
|
||||
public static final Object SNOW;
|
||||
public static final Object WATER;
|
||||
public static final Object WATER$defaultState;
|
||||
public static final Object TNT;
|
||||
public static final Object TNT$defaultState;
|
||||
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
@@ -41,5 +43,7 @@ public final class MBlocks {
|
||||
SNOW = getById("snow");
|
||||
WATER = getById("water");
|
||||
WATER$defaultState = FastNMS.INSTANCE.method$Block$defaultState(WATER);
|
||||
TNT = getById("tnt");
|
||||
TNT$defaultState = FastNMS.INSTANCE.method$Block$defaultState(TNT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,24 @@ public final class MEntityTypes {
|
||||
public static final int HAPPY_GHAST$registryId;
|
||||
public static final Object PLAYER;
|
||||
public static final int PLAYER$registryId;
|
||||
public static final Object ENDERMAN;
|
||||
public static final int ENDERMAN$registryId;
|
||||
public static final Object TNT;
|
||||
public static final int TNT$registryId;
|
||||
public static final Object CHEST_MINECART;
|
||||
public static final int CHEST_MINECART$registryId;
|
||||
public static final Object COMMAND_BLOCK_MINECART;
|
||||
public static final int COMMAND_BLOCK_MINECART$registryId;
|
||||
public static final Object FURNACE_MINECART;
|
||||
public static final int FURNACE_MINECART$registryId;
|
||||
public static final Object HOPPER_MINECART;
|
||||
public static final int HOPPER_MINECART$registryId;
|
||||
public static final Object MINECART;
|
||||
public static final int MINECART$registryId;
|
||||
public static final Object SPAWNER_MINECART;
|
||||
public static final int SPAWNER_MINECART$registryId;
|
||||
public static final Object TNT_MINECART;
|
||||
public static final int TNT_MINECART$registryId;
|
||||
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
@@ -122,5 +140,23 @@ public final class MEntityTypes {
|
||||
ARROW$registryId = getRegistryId(ARROW);
|
||||
SPECTRAL_ARROW = getById("spectral_arrow");
|
||||
SPECTRAL_ARROW$registryId = getRegistryId(SPECTRAL_ARROW);
|
||||
ENDERMAN = getById("enderman");
|
||||
ENDERMAN$registryId = getRegistryId(ENDERMAN);
|
||||
TNT = getById("tnt");
|
||||
TNT$registryId = getRegistryId(TNT);
|
||||
CHEST_MINECART = getById("chest_minecart");
|
||||
CHEST_MINECART$registryId = getRegistryId(CHEST_MINECART);
|
||||
COMMAND_BLOCK_MINECART = getById("command_block_minecart");
|
||||
COMMAND_BLOCK_MINECART$registryId = getRegistryId(COMMAND_BLOCK_MINECART);
|
||||
FURNACE_MINECART = getById("furnace_minecart");
|
||||
FURNACE_MINECART$registryId = getRegistryId(FURNACE_MINECART);
|
||||
HOPPER_MINECART = getById("hopper_minecart");
|
||||
HOPPER_MINECART$registryId = getRegistryId(HOPPER_MINECART);
|
||||
MINECART = getById("minecart");
|
||||
MINECART$registryId = getRegistryId(MINECART);
|
||||
SPAWNER_MINECART = getById("spawner_minecart");
|
||||
SPAWNER_MINECART$registryId = getRegistryId(SPAWNER_MINECART);
|
||||
TNT_MINECART = getById("tnt_minecart");
|
||||
TNT_MINECART$registryId = getRegistryId(TNT_MINECART);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.gui.CraftEngineInventoryHolder;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.payload.DiscardedPayload;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MMobEffects;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.BlockSettings;
|
||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.player.GameMode;
|
||||
@@ -111,14 +111,16 @@ public class BukkitServerPlayer extends Player {
|
||||
|
||||
private final Map<Integer, EntityPacketHandler> entityTypeView = new ConcurrentHashMap<>();
|
||||
|
||||
public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) {
|
||||
public BukkitServerPlayer(BukkitCraftEngine plugin, @Nullable Channel channel) {
|
||||
this.channel = channel;
|
||||
this.plugin = plugin;
|
||||
for (String name : channel.pipeline().names()) {
|
||||
ChannelHandler handler = channel.pipeline().get(name);
|
||||
if (NetworkReflections.clazz$Connection.isInstance(handler)) {
|
||||
this.connection = handler;
|
||||
break;
|
||||
if (channel != null) {
|
||||
for (String name : channel.pipeline().names()) {
|
||||
ChannelHandler handler = channel.pipeline().get(name);
|
||||
if (NetworkReflections.clazz$Connection.isInstance(handler)) {
|
||||
this.connection = handler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,6 +187,7 @@ public class BukkitServerPlayer extends Player {
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@Override
|
||||
public void setGameMode(GameMode gameMode) {
|
||||
platformPlayer().setGameMode(Objects.requireNonNull(org.bukkit.GameMode.getByValue(gameMode.id())));
|
||||
@@ -327,22 +330,37 @@ public class BukkitServerPlayer extends Player {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendCustomPayload(Key channel, byte[] data) {
|
||||
public void sendPackets(List<Object> packet, boolean immediately) {
|
||||
this.plugin.networkManager().sendPackets(this, packet, immediately);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPackets(List<Object> packet, boolean immediately, Runnable sendListener) {
|
||||
this.plugin.networkManager().sendPackets(this, packet, immediately, sendListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simulatePacket(Object packet) {
|
||||
this.plugin.networkManager().simulatePacket(this, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendCustomPayload(Key channelId, byte[] data) {
|
||||
try {
|
||||
Object channelKey = KeyUtils.toResourceLocation(channel);
|
||||
Object channelResourceLocation = KeyUtils.toResourceLocation(channelId);
|
||||
Object responsePacket;
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
Object dataPayload;
|
||||
if (NetworkReflections.clazz$UnknownPayload != null) {
|
||||
dataPayload = NetworkReflections.constructor$UnknownPayload.newInstance(channelKey, Unpooled.wrappedBuffer(data));
|
||||
dataPayload = NetworkReflections.constructor$UnknownPayload.newInstance(channelResourceLocation, Unpooled.wrappedBuffer(data));
|
||||
} else if (DiscardedPayload.useNewMethod) {
|
||||
dataPayload = NetworkReflections.constructor$DiscardedPayload.newInstance(channelKey, data);
|
||||
dataPayload = NetworkReflections.constructor$DiscardedPayload.newInstance(channelResourceLocation, data);
|
||||
} else {
|
||||
dataPayload = NetworkReflections.constructor$DiscardedPayload.newInstance(channelKey, Unpooled.wrappedBuffer(data));
|
||||
dataPayload = NetworkReflections.constructor$DiscardedPayload.newInstance(channelResourceLocation, Unpooled.wrappedBuffer(data));
|
||||
}
|
||||
responsePacket = NetworkReflections.constructor$ClientboundCustomPayloadPacket.newInstance(dataPayload);
|
||||
} else {
|
||||
responsePacket = NetworkReflections.constructor$ClientboundCustomPayloadPacket.newInstance(channelKey, FastNMS.INSTANCE.constructor$FriendlyByteBuf(Unpooled.wrappedBuffer(data)));
|
||||
responsePacket = NetworkReflections.constructor$ClientboundCustomPayloadPacket.newInstance(channelResourceLocation, FastNMS.INSTANCE.constructor$FriendlyByteBuf(Unpooled.wrappedBuffer(data)));
|
||||
}
|
||||
this.sendPacket(responsePacket, true);
|
||||
} catch (Exception e) {
|
||||
@@ -364,21 +382,6 @@ public class BukkitServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPackets(List<Object> packet, boolean immediately) {
|
||||
this.plugin.networkManager().sendPackets(this, packet, immediately);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPackets(List<Object> packet, boolean immediately, Runnable sendListener) {
|
||||
this.plugin.networkManager().sendPackets(this, packet, immediately, sendListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simulatePacket(Object packet) {
|
||||
this.plugin.networkManager().simulatePacket(this, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionState decoderState() {
|
||||
return decoderState;
|
||||
@@ -456,6 +459,9 @@ public class BukkitServerPlayer extends Player {
|
||||
|
||||
private void updateGUI() {
|
||||
org.bukkit.inventory.Inventory top = !VersionHelper.isOrAbove1_21() ? LegacyInventoryUtils.getTopInventory(platformPlayer()) : platformPlayer().getOpenInventory().getTopInventory();
|
||||
if (!CraftBukkitReflections.clazz$MinecraftInventory.isInstance(FastNMS.INSTANCE.method$CraftInventory$getInventory(top))) {
|
||||
return;
|
||||
}
|
||||
if (top.getHolder() instanceof CraftEngineInventoryHolder holder) {
|
||||
holder.gui().onTimer();
|
||||
}
|
||||
@@ -463,7 +469,21 @@ public class BukkitServerPlayer extends Player {
|
||||
|
||||
@Override
|
||||
public float getDestroyProgress(Object blockState, BlockPos pos) {
|
||||
return FastNMS.INSTANCE.method$BlockStateBase$getDestroyProgress(blockState, serverPlayer(), FastNMS.INSTANCE.field$CraftWorld$ServerLevel(platformPlayer().getWorld()), LocationUtils.toBlockPos(pos));
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
float progress = FastNMS.INSTANCE.method$BlockStateBase$getDestroyProgress(blockState, serverPlayer(), FastNMS.INSTANCE.field$CraftWorld$ServerLevel(platformPlayer().getWorld()), LocationUtils.toBlockPos(pos));
|
||||
if (optionalCustomState.isPresent()) {
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
Item<ItemStack> tool = getItemInHand(InteractionHand.MAIN_HAND);
|
||||
boolean isCorrectTool = FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(tool.getLiteralObject(), blockState);
|
||||
// 如果自定义方块在服务端侧未使用正确地工具,那么需要还原挖掘速度
|
||||
if (!isCorrectTool) {
|
||||
progress *= (10f / 3f);
|
||||
}
|
||||
if (!BlockStateUtils.isCorrectTool(customState, tool)) {
|
||||
progress *= customState.settings().incorrectToolSpeed();
|
||||
}
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
private void predictNextBlockToMine() {
|
||||
@@ -648,28 +668,6 @@ public class BukkitServerPlayer extends Player {
|
||||
// double check custom block
|
||||
if (optionalCustomState.isPresent()) {
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
BlockSettings blockSettings = customState.settings();
|
||||
if (blockSettings.requireCorrectTool()) {
|
||||
if (!item.isEmpty()) {
|
||||
// it's correct on plugin side
|
||||
if (blockSettings.isCorrectTool(item.id())) {
|
||||
// but not on serverside
|
||||
if (!FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), destroyedState)) {
|
||||
// we fix the speed
|
||||
progressToAdd = progressToAdd * (10f / 3f);
|
||||
}
|
||||
} else {
|
||||
// not a correct tool on plugin side and not a correct tool on serverside
|
||||
if (!blockSettings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), destroyedState)) {
|
||||
progressToAdd = progressToAdd * (10f / 3f) * blockSettings.incorrectToolSpeed();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// item is null, but it requires correct tool, then we reset the speed
|
||||
progressToAdd = progressToAdd * (10f / 3f) * blockSettings.incorrectToolSpeed();
|
||||
}
|
||||
}
|
||||
|
||||
// accumulate progress
|
||||
this.miningProgress = progressToAdd + miningProgress;
|
||||
int packetStage = (int) (this.miningProgress * 10.0F);
|
||||
@@ -857,6 +855,11 @@ public class BukkitServerPlayer extends Player {
|
||||
return this.connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFakePlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.entity.Player literalObject() {
|
||||
return platformPlayer();
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.user;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
|
||||
public class FakeBukkitServerPlayer extends BukkitServerPlayer {
|
||||
|
||||
public FakeBukkitServerPlayer(BukkitCraftEngine plugin) {
|
||||
super(plugin, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Channel nettyChannel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler connection() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kick(Component message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFakePlayer() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import org.bukkit.Location;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public class AdventureModeUtils {
|
||||
public final class AdventureModeUtils {
|
||||
|
||||
private AdventureModeUtils() {}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class BlockStateUtils {
|
||||
public final class BlockStateUtils {
|
||||
public static final IdentityHashMap<Object, Object> CLIENT_SIDE_NOTE_BLOCKS = new IdentityHashMap<>();
|
||||
private static int vanillaStateSize;
|
||||
private static boolean hasInit;
|
||||
|
||||
@@ -7,7 +7,7 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BlockTags {
|
||||
public final class BlockTags {
|
||||
private static final Map<Key, Object> CACHE = new HashMap<>();
|
||||
|
||||
private BlockTags() {}
|
||||
|
||||
@@ -6,7 +6,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.paper.PaperReflections;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
|
||||
public class ComponentUtils {
|
||||
public final class ComponentUtils {
|
||||
|
||||
private ComponentUtils() {}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
import net.momirealms.craftengine.core.util.DamageSource;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
|
||||
public class DamageCauseUtils {
|
||||
public final class DamageCauseUtils {
|
||||
|
||||
private DamageCauseUtils() {}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
public class DirectionUtils {
|
||||
public final class DirectionUtils {
|
||||
|
||||
private DirectionUtils() {}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class DummyListener implements Listener {
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EnchantmentUtils {
|
||||
public final class EnchantmentUtils {
|
||||
|
||||
private EnchantmentUtils() {}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
public class EntityDataUtils {
|
||||
public final class EntityDataUtils {
|
||||
|
||||
private EntityDataUtils() {}
|
||||
|
||||
@@ -11,12 +9,7 @@ public class EntityDataUtils {
|
||||
private static final int USE_DEFAULT_BACKGROUND = 0x04; // 4
|
||||
private static final int LEFT_ALIGNMENT = 0x08; // 8
|
||||
private static final int RIGHT_ALIGNMENT = 0x10; // 16
|
||||
public static final int BLOCK_STATE_DATA_ID = VersionHelper.isOrAbove1_20_2() ? 23 : 22;
|
||||
public static final int TEXT_DATA_ID = VersionHelper.isOrAbove1_20_2() ? 23 : 22;
|
||||
public static final int DISPLAYED_ITEM_DATA_ID = VersionHelper.isOrAbove1_20_2() ? 23 : 22;
|
||||
public static final int CUSTOM_NAME_DATA_ID = 2;
|
||||
public static final int ITEM_DATA_ID = 8;
|
||||
public static final int ITEM_FRAME_DATA_ID = VersionHelper.isOrAbove1_21_6() ? 9 : 8;
|
||||
public static final int UNSAFE_ITEM_DATA_ID = 8; // 正常来说应该通过定义 Data 获取 id 这样的做法未经验证可能不安全
|
||||
|
||||
public static byte encodeTextDisplayMask(boolean hasShadow, boolean isSeeThrough, boolean useDefaultBackground, int alignment) {
|
||||
int bitMask = 0;
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EntityUtils {
|
||||
public final class EntityUtils {
|
||||
|
||||
private EntityUtils() {
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
public class EventUtils {
|
||||
public final class EventUtils {
|
||||
|
||||
private EventUtils() {}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class ExplosionUtils {
|
||||
public final class ExplosionUtils {
|
||||
|
||||
public static boolean isDroppingItems(BlockExplodeEvent event) {
|
||||
return event.getExplosionResult() != ExplosionResult.KEEP && event.getExplosionResult() != ExplosionResult.TRIGGER_BLOCK;
|
||||
|
||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
public class FeatureUtils {
|
||||
public final class FeatureUtils {
|
||||
|
||||
private FeatureUtils() {}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
import net.momirealms.craftengine.core.world.FluidCollisionRule;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
|
||||
public class FluidUtils {
|
||||
public final class FluidUtils {
|
||||
|
||||
private FluidUtils() {}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class InteractUtils {
|
||||
public final class InteractUtils {
|
||||
private static final Map<Key, QuadFunction<Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean>> INTERACTIONS = new HashMap<>();
|
||||
private static final Map<Key, QuadFunction<Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean>> WILL_CONSUME = new HashMap<>();
|
||||
private static final Map<Key, TriFunction<Player, Entity, @Nullable Item<ItemStack>, Boolean>> ENTITY_INTERACTIONS = new HashMap<>();
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.bukkit.event.inventory.InventoryEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
public class InventoryUtils {
|
||||
public final class InventoryUtils {
|
||||
|
||||
private InventoryUtils() {}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemTags {
|
||||
public final class ItemTags {
|
||||
private static final Map<Key, Object> CACHE = new HashMap<>();
|
||||
|
||||
public static final Key AXES = Key.of("minecraft:axes");
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class LightUtils {
|
||||
public final class LightUtils {
|
||||
|
||||
private LightUtils() {}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class LocationUtils {
|
||||
public final class LocationUtils {
|
||||
|
||||
private LocationUtils() {}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MaterialUtils {
|
||||
public final class MaterialUtils {
|
||||
|
||||
public static Material MACE;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.core.util.Mirror;
|
||||
|
||||
public class MirrorUtils {
|
||||
public final class MirrorUtils {
|
||||
|
||||
private MirrorUtils() {}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
|
||||
public class MobEffectUtils {
|
||||
public final class MobEffectUtils {
|
||||
|
||||
private MobEffectUtils() {}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
|
||||
public class NoteBlockChainUpdateUtils {
|
||||
public final class NoteBlockChainUpdateUtils {
|
||||
|
||||
private NoteBlockChainUpdateUtils() {}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
public class OptimizedReflections {
|
||||
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user