mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-27 10:59:07 +00:00
@@ -91,7 +91,7 @@ Given the extensive and intricate nature of plugin configurations, a modular tem
|
||||
The plugin enables model inheritance and texture overrides through configuration, while supporting [all item models](https://misode.github.io/assets/item/) from version 1.21.4 onward. It incorporates a version migration system that automatically downgrades 1.21.4+ item models to legacy formats with maximum backward compatibility.
|
||||
|
||||
### Breaking Changes You Have to Know & Possible Incompatibility with Other Plugins
|
||||
- CraftEngine injects into PalettedContainer to ensure efficient storage and synchronization of plugin block data. This may cause conflicts with some other plugins that modify the palette. When analyzing server performance using Spark, palette operation overhead will be attributed to the CraftEngine plugin in the profiling results..
|
||||
- CraftEngine injects into PalettedContainer to ensure efficient storage and synchronization of plugin block data. This may cause conflicts with some other plugins that modify the palette. When analyzing server performance using Spark, palette operation overhead will be attributed to the CraftEngine plugin in the profiling results.
|
||||
- CraftEngine injects into FurnaceBlockEntity to modify its recipe fetching logic.
|
||||
- CraftEngine uses real server-side blocks, any plugin relying on Bukkit's Material class will fail to correctly identify custom block types. The proper approach is to use alternatives like BlockState#getBlock (mojmap) instead of the Material class.
|
||||
- CraftEngine implements 0-tick collision entities by extending certain Minecraft entities, ensuring hard collision works correctly on the server side (e.g., making a pig stand on a chair). However, some anti-cheat plugins do not check entity AABB (Axis-Aligned Bounding Box) properly when detecting player movement, which may lead to false flags.
|
||||
|
||||
@@ -13,7 +13,6 @@ repositories {
|
||||
dependencies {
|
||||
compileOnly(project(":core"))
|
||||
compileOnly(project(":shared"))
|
||||
compileOnly(project(":bukkit:compatibility"))
|
||||
compileOnly(project(":bukkit:legacy"))
|
||||
// Anti Grief
|
||||
compileOnly("net.momirealms:antigrieflib:${rootProject.properties["anti_grief_version"]}")
|
||||
|
||||
@@ -9,11 +9,17 @@ repositories {
|
||||
maven("https://repo.momirealms.net/releases/")
|
||||
maven("https://mvn.lumine.io/repository/maven-public/") // model engine
|
||||
maven("https://nexus.phoenixdevt.fr/repository/maven-public/") // mmoitems
|
||||
maven("https://repo.viaversion.com") // via
|
||||
maven("https://repo.skriptlang.org/releases/") // skript
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":core"))
|
||||
compileOnly(project(":bukkit"))
|
||||
compileOnly(project(":bukkit:compatibility:legacy"))
|
||||
compileOnly("net.momirealms:sparrow-nbt:${rootProject.properties["sparrow_nbt_version"]}")
|
||||
// NMS
|
||||
compileOnly("net.momirealms:craft-engine-nms-helper:${rootProject.properties["nms_helper_version"]}")
|
||||
// Platform
|
||||
compileOnly("io.papermc.paper:paper-api:${rootProject.properties["paper_version"]}-R0.1-SNAPSHOT")
|
||||
// NeigeItems
|
||||
@@ -34,6 +40,10 @@ dependencies {
|
||||
compileOnly("io.lumine:MythicLib-dist:1.6.2-SNAPSHOT")
|
||||
// LuckPerms
|
||||
compileOnly("net.luckperms:api:5.4")
|
||||
// viaversion
|
||||
compileOnly("com.viaversion:viaversion-api:5.3.2")
|
||||
// Skript
|
||||
compileOnly("com.github.SkriptLang:Skript:2.11.0")
|
||||
}
|
||||
|
||||
java {
|
||||
|
||||
31
bukkit/compatibility/legacy/build.gradle.kts
Normal file
31
bukkit/compatibility/legacy/build.gradle.kts
Normal file
@@ -0,0 +1,31 @@
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
maven("https://repo.rapture.pw/repository/maven-releases/")
|
||||
maven("https://repo.momirealms.net/releases/")
|
||||
maven("https://repo.infernalsuite.com/repository/maven-snapshots/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":core"))
|
||||
// NBT
|
||||
compileOnly("net.momirealms:sparrow-nbt:${rootProject.properties["sparrow_nbt_version"]}")
|
||||
// Platform
|
||||
compileOnly("io.papermc.paper:paper-api:${rootProject.properties["paper_version"]}-R0.1-SNAPSHOT")
|
||||
compileOnly("com.infernalsuite.aswm:api:1.20.4-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
options.encoding = "UTF-8"
|
||||
options.release.set(21)
|
||||
dependsOn(tasks.clean)
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.legacy.slimeworld;
|
||||
|
||||
import com.infernalsuite.aswm.api.events.LoadSlimeWorldEvent;
|
||||
import com.infernalsuite.aswm.api.world.SlimeWorld;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldManager;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.DefaultStorageAdaptor;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class LegacySlimeFormatStorageAdaptor extends DefaultStorageAdaptor implements Listener {
|
||||
private final WorldManager worldManager;
|
||||
private final Function<String, SlimeWorld> SLIME_WORLD_GETTER;
|
||||
|
||||
@EventHandler
|
||||
public void onWorldLoad(LoadSlimeWorldEvent event) {
|
||||
org.bukkit.World world = Bukkit.getWorld(event.getSlimeWorld().getName());
|
||||
this.worldManager.loadWorld(this.worldManager.createWorld(this.worldManager.wrap(world), new LegacySlimeWorldDataStorage(event.getSlimeWorld())));
|
||||
}
|
||||
|
||||
public LegacySlimeFormatStorageAdaptor(WorldManager worldManager, int version) {
|
||||
this.worldManager = worldManager;
|
||||
try {
|
||||
if (version == 1) {
|
||||
Plugin plugin = Bukkit.getPluginManager().getPlugin("SlimeWorldManager");
|
||||
Class<?> slimeClass = Class.forName("com.infernalsuite.aswm.api.SlimePlugin");
|
||||
Method method = slimeClass.getMethod("getWorld", String.class);
|
||||
this.SLIME_WORLD_GETTER = (name) -> {
|
||||
try {
|
||||
return (SlimeWorld) method.invoke(plugin, name);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
} else if (version == 2) {
|
||||
Class<?> apiClass = Class.forName("com.infernalsuite.aswm.api.AdvancedSlimePaperAPI");
|
||||
Object apiInstance = apiClass.getMethod("instance").invoke(null);
|
||||
Method method = apiClass.getMethod("getLoadedWorld", String.class);
|
||||
this.SLIME_WORLD_GETTER = (name) -> {
|
||||
try {
|
||||
return (SlimeWorld) method.invoke(apiInstance, name);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported version: " + version);
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public SlimeWorld getWorld(String name) {
|
||||
return this.SLIME_WORLD_GETTER.apply(name);
|
||||
}
|
||||
|
||||
// 请注意,在加载事件的时候,无法通过AdvancedSlimePaperAPI.instance().getLoadedWorld来判断是否为slime世界
|
||||
@Override
|
||||
public @NotNull WorldDataStorage adapt(@NotNull World world) {
|
||||
SlimeWorld slimeWorld = getWorld(world.name());
|
||||
if (slimeWorld == null) {
|
||||
return super.adapt(world);
|
||||
}
|
||||
return new LegacySlimeWorldDataStorage(slimeWorld);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.legacy.slimeworld;
|
||||
|
||||
import com.flowpowered.nbt.ByteArrayTag;
|
||||
import com.flowpowered.nbt.CompoundMap;
|
||||
import com.infernalsuite.aswm.api.world.SlimeChunk;
|
||||
import com.infernalsuite.aswm.api.world.SlimeWorld;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||
import net.momirealms.craftengine.core.world.chunk.serialization.DefaultChunkSerializer;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.NBT;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Optional;
|
||||
|
||||
public class LegacySlimeWorldDataStorage implements WorldDataStorage {
|
||||
private final WeakReference<com.infernalsuite.aswm.api.world.SlimeWorld> slimeWorld;
|
||||
|
||||
public LegacySlimeWorldDataStorage(SlimeWorld slimeWorld) {
|
||||
this.slimeWorld = new WeakReference<>(slimeWorld);
|
||||
}
|
||||
|
||||
public SlimeWorld getWorld() {
|
||||
return slimeWorld.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CEChunk readChunkAt(@NotNull CEWorld world, @NotNull ChunkPos pos) {
|
||||
SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z);
|
||||
if (slimeChunk == null) return new CEChunk(world, pos);
|
||||
Optional<ByteArrayTag> tag = slimeChunk.getExtraData().getAsByteArrayTag("craftengine");
|
||||
if (tag.isEmpty()) return new CEChunk(world, pos);
|
||||
try {
|
||||
CompoundTag compoundTag = NBT.fromBytes(tag.get().getValue());
|
||||
if (compoundTag == null) return new CEChunk(world, pos);
|
||||
return DefaultChunkSerializer.deserialize(world, pos, compoundTag);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to read chunk tag from slime world. " + pos, e);
|
||||
}
|
||||
}
|
||||
|
||||
private CompoundMap createOrGetDataMap(SlimeWorld world) {
|
||||
Optional<com.flowpowered.nbt.CompoundTag> optionalCompoundTag = world.getExtraData().getAsCompoundTag("craftengine");
|
||||
CompoundMap ccDataMap;
|
||||
if (optionalCompoundTag.isEmpty()) {
|
||||
ccDataMap = new CompoundMap();
|
||||
world.getExtraData().getValue().put(new com.flowpowered.nbt.CompoundTag("customcrops", ccDataMap));
|
||||
} else {
|
||||
ccDataMap = optionalCompoundTag.get().getValue();
|
||||
}
|
||||
return ccDataMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeChunkAt(@NotNull ChunkPos pos, @NotNull CEChunk chunk, boolean immediately) {
|
||||
SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z);
|
||||
if (slimeChunk == null) return;
|
||||
CompoundTag nbt = DefaultChunkSerializer.serialize(chunk);
|
||||
if (nbt == null) {
|
||||
slimeChunk.getExtraData().getValue().remove("craftengine");
|
||||
} else {
|
||||
try {
|
||||
slimeChunk.getExtraData().getValue().put("craftengine", new ByteArrayTag("craftengine", NBT.toBytes(nbt)));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to write chunk tag to slime world. " + pos, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.bettermodel.BetterModelModel;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.item.MMOItemsProvider;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsProvider;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.legacy.slimeworld.LegacySlimeFormatStorageAdaptor;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineModel;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineUtils;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.papi.PlaceholderAPIUtils;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.permission.LuckPermsEventListeners;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.SkriptHook;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.slimeworld.SlimeFormatStorageAdaptor;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.viaversion.ViaVersionUtils;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.worldedit.WorldEditBlockRegister;
|
||||
import net.momirealms.craftengine.bukkit.font.BukkitFontManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.core.entity.furniture.AbstractExternalModel;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.CompatibilityManager;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.WorldManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitCompatibilityManager implements CompatibilityManager {
|
||||
private final BukkitCraftEngine plugin;
|
||||
private boolean hasPlaceholderAPI;
|
||||
private boolean hasViaVersion;
|
||||
|
||||
public BukkitCompatibilityManager(BukkitCraftEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
this.initSlimeWorldHook();
|
||||
if (this.isPluginEnabled("PlaceholderAPI")) {
|
||||
PlaceholderAPIUtils.registerExpansions(this.plugin);
|
||||
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));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDelayedEnable() {
|
||||
this.initItemHooks();
|
||||
// WorldEdit
|
||||
if (this.isPluginEnabled("FastAsyncWorldEdit")) {
|
||||
this.initFastAsyncWorldEditHook();
|
||||
logHook("FastAsyncWorldEdit");
|
||||
} else if (this.isPluginEnabled("WorldEdit")) {
|
||||
this.initWorldEditHook();
|
||||
logHook("WorldEdit");
|
||||
}
|
||||
if (this.isPluginEnabled("LuckPerms")) {
|
||||
this.initLuckPermsHook();
|
||||
logHook("LuckPerms");
|
||||
}
|
||||
}
|
||||
|
||||
private void logHook(String plugin) {
|
||||
this.plugin.logger().info("[Compatibility] " + plugin + " hooked");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractExternalModel createModelEngineModel(String id) {
|
||||
return new ModelEngineModel(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractExternalModel createBetterModelModel(String id) {
|
||||
return new BetterModelModel(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int interactionToBaseEntity(int id) {
|
||||
return ModelEngineUtils.interactionToBaseEntity(id);
|
||||
}
|
||||
|
||||
private void initLuckPermsHook() {
|
||||
new LuckPermsEventListeners(plugin.bootstrap(), (uuid) -> {
|
||||
BukkitFontManager fontManager = (BukkitFontManager) plugin.fontManager();
|
||||
fontManager.refreshEmojiSuggestions(uuid);
|
||||
});
|
||||
}
|
||||
|
||||
private void initSlimeWorldHook() {
|
||||
WorldManager worldManager = this.plugin.worldManager();
|
||||
if (VersionHelper.isOrAbove1_21_4()) {
|
||||
try {
|
||||
Class.forName("com.infernalsuite.asp.api.AdvancedSlimePaperAPI");
|
||||
SlimeFormatStorageAdaptor adaptor = new SlimeFormatStorageAdaptor(worldManager);
|
||||
worldManager.setStorageAdaptor(adaptor);
|
||||
Bukkit.getPluginManager().registerEvents(adaptor, plugin.bootstrap());
|
||||
logHook("AdvancedSlimePaper");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Class.forName("com.infernalsuite.aswm.api.SlimePlugin");
|
||||
LegacySlimeFormatStorageAdaptor adaptor = new LegacySlimeFormatStorageAdaptor(worldManager, 1);
|
||||
worldManager.setStorageAdaptor(adaptor);
|
||||
Bukkit.getPluginManager().registerEvents(adaptor, plugin.bootstrap());
|
||||
logHook("AdvancedSlimePaper");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("SlimeWorldPlugin")) {
|
||||
LegacySlimeFormatStorageAdaptor adaptor = new LegacySlimeFormatStorageAdaptor(worldManager, 2);
|
||||
worldManager.setStorageAdaptor(adaptor);
|
||||
Bukkit.getPluginManager().registerEvents(adaptor, plugin.bootstrap());
|
||||
logHook("AdvancedSlimePaper");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initFastAsyncWorldEditHook() {
|
||||
new WorldEditBlockRegister(BukkitBlockManager.instance(), true);
|
||||
}
|
||||
|
||||
private void initWorldEditHook() {
|
||||
WorldEditBlockRegister weBlockRegister = new WorldEditBlockRegister(BukkitBlockManager.instance(), false);
|
||||
try {
|
||||
for (Key newBlockId : BukkitBlockManager.instance().blockRegisterOrder()) {
|
||||
weBlockRegister.register(newBlockId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to initialize world edit hook", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void initItemHooks() {
|
||||
BukkitItemManager itemManager = BukkitItemManager.instance();
|
||||
if (this.isPluginEnabled("NeigeItems")) {
|
||||
itemManager.registerExternalItemProvider(new NeigeItemsProvider());
|
||||
logHook("NeigeItems");
|
||||
}
|
||||
if (this.isPluginEnabled("MMOItems")) {
|
||||
itemManager.registerExternalItemProvider(new MMOItemsProvider());
|
||||
logHook("MMOItems");
|
||||
}
|
||||
}
|
||||
|
||||
private Plugin getPlugin(String name) {
|
||||
return Bukkit.getPluginManager().getPlugin(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlaceholderAPI() {
|
||||
return this.hasPlaceholderAPI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginEnabled(String plugin) {
|
||||
return Bukkit.getPluginManager().isPluginEnabled(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlugin(String plugin) {
|
||||
return Bukkit.getPluginManager().getPlugin(plugin) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parse(Player player, String text) {
|
||||
return PlaceholderAPIUtils.parse((org.bukkit.entity.Player) player.platformPlayer(), text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerProtocolVersion(UUID uuid) {
|
||||
return ViaVersionUtils.getPlayerProtocolVersion(uuid);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class LuckPermsEventListeners {
|
||||
private final JavaPlugin plugin;
|
||||
@@ -42,16 +41,16 @@ public class LuckPermsEventListeners {
|
||||
this.subscriptions.add(eventBus.subscribe(this.plugin, GroupDataRecalculateEvent.class, this::onGroupPermissionChange));
|
||||
}
|
||||
|
||||
public void unregisterListeners() {
|
||||
this.subscriptions.forEach(subscription -> {
|
||||
try {
|
||||
subscription.close();
|
||||
} catch (Exception e) {
|
||||
this.plugin.getLogger().log(Level.WARNING, "Failed to close event subscription", e);
|
||||
}
|
||||
});
|
||||
this.subscriptions.clear();
|
||||
}
|
||||
// public void unregisterListeners() {
|
||||
// this.subscriptions.forEach(subscription -> {
|
||||
// try {
|
||||
// subscription.close();
|
||||
// } catch (Exception e) {
|
||||
// this.plugin.getLogger().log(Level.WARNING, "Failed to close event subscription", e);
|
||||
// }
|
||||
// });
|
||||
// this.subscriptions.clear();
|
||||
// }
|
||||
|
||||
private void onUserPermissionChange(UserDataRecalculateEvent event) {
|
||||
CraftEngine.instance().scheduler().async().execute(() -> {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.clazz.CraftEngineClasses;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsCustomBlock;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsCustomItem;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsFurniture;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.effect.EffPlaceCustomBlock;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.effect.EffPlaceFurniture;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.effect.EffRemoveFurniture;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomBlock;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomClick;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomFurniture;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.expression.*;
|
||||
|
||||
public class SkriptHook {
|
||||
|
||||
public static void register() {
|
||||
CraftEngineClasses.register();
|
||||
EvtCustomBlock.register();
|
||||
EvtCustomFurniture.register();
|
||||
EvtCustomClick.register();
|
||||
CondIsCustomBlock.register();
|
||||
CondIsFurniture.register();
|
||||
CondIsCustomItem.register();
|
||||
ExprBlockCustomBlockID.register();
|
||||
ExprItemCustomItemID.register();
|
||||
ExprBlockCustomBlockState.register();
|
||||
ExprCustomItem.register();
|
||||
ExprEntityFurnitureID.register();
|
||||
EffPlaceCustomBlock.register();
|
||||
EffPlaceFurniture.register();
|
||||
EffRemoveFurniture.register();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.clazz;
|
||||
|
||||
import ch.njol.skript.classes.ClassInfo;
|
||||
import ch.njol.skript.classes.Parser;
|
||||
import ch.njol.skript.classes.Serializer;
|
||||
import ch.njol.skript.lang.ParseContext;
|
||||
import ch.njol.skript.registrations.Classes;
|
||||
import ch.njol.yggdrasil.Fields;
|
||||
import net.momirealms.craftengine.core.block.BlockStateParser;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UnsafeBlockStateMatcher;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.StreamCorruptedException;
|
||||
|
||||
public class CraftEngineClasses {
|
||||
|
||||
public static void register() {
|
||||
Classes.registerClass(new ClassInfo<>(ImmutableBlockState.class, "customblockstate")
|
||||
.user("custom block state")
|
||||
.name("Custom Block State")
|
||||
.serializer(new Serializer<>() {
|
||||
@Override
|
||||
public Fields serialize(ImmutableBlockState o) {
|
||||
Fields f = new Fields();
|
||||
f.putObject("customblockstate", o.toString());
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(ImmutableBlockState o, Fields f) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableBlockState deserialize(Fields f) throws StreamCorruptedException {
|
||||
String data = f.getObject("customblockstate", String.class);
|
||||
assert data != null;
|
||||
try {
|
||||
return BlockStateParser.deserialize(data);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new StreamCorruptedException("Invalid block data: " + data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mustSyncDeserialization() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canBeInstantiated() {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.parser(new Parser<>() {
|
||||
@Override
|
||||
public String toString(ImmutableBlockState o, int flags) {
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVariableNameString(ImmutableBlockState o) {
|
||||
return "customblockstate:" + o.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ImmutableBlockState parse(String s, ParseContext context) {
|
||||
return BlockStateParser.deserialize(s);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
Classes.registerClass(new ClassInfo<>(UnsafeBlockStateMatcher.class, "unsafeblockstatematcher")
|
||||
.user("unsafe block state matcher")
|
||||
.name("Unsafe Block State Matcher")
|
||||
.serializer(new Serializer<>() {
|
||||
@Override
|
||||
public Fields serialize(UnsafeBlockStateMatcher o) {
|
||||
Fields f = new Fields();
|
||||
f.putObject("unsafeblockstatematcher", o.toString());
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(UnsafeBlockStateMatcher o, Fields f) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnsafeBlockStateMatcher deserialize(Fields f) throws StreamCorruptedException {
|
||||
String data = f.getObject("unsafeblockstatematcher", String.class);
|
||||
assert data != null;
|
||||
try {
|
||||
return UnsafeBlockStateMatcher.deserialize(data);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new StreamCorruptedException("Invalid block matcher: " + data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mustSyncDeserialization() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canBeInstantiated() {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.parser(new Parser<>() {
|
||||
@Override
|
||||
public String toString(UnsafeBlockStateMatcher o, int flags) {
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVariableNameString(UnsafeBlockStateMatcher o) {
|
||||
return "unsafeblockstatematcher:" + o.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UnsafeBlockStateMatcher parse(String s, ParseContext context) {
|
||||
return UnsafeBlockStateMatcher.deserialize(s);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.condition;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.conditions.base.PropertyCondition;
|
||||
import ch.njol.skript.lang.Condition;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
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)");
|
||||
}
|
||||
|
||||
private Expression<Block> blocks;
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
return blocks.check(event, CraftEngineBlocks::isCustomBlock, isNegated());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return PropertyCondition.toString(this, PropertyCondition.PropertyType.BE, event, debug, blocks, "custom block");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
blocks = (Expression<Block>) expressions[0];
|
||||
setNegated(matchedPattern > 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.condition;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.conditions.base.PropertyCondition;
|
||||
import ch.njol.skript.lang.Condition;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CondIsCustomItem extends Condition {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerCondition(CondIsCustomItem.class,
|
||||
"%itemstacks% (is|are) custom item(s)",
|
||||
"%itemstacks% (is|are)(n't| not) custom item(s)");
|
||||
}
|
||||
|
||||
private Expression<ItemStack> items;
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
return items.check(event, CraftEngineItems::isCustomItem, isNegated());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return PropertyCondition.toString(this, PropertyCondition.PropertyType.BE, event, debug, items, "itemstack");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
items = (Expression<ItemStack>) expressions[0];
|
||||
setNegated(matchedPattern > 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.condition;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.conditions.base.PropertyCondition;
|
||||
import ch.njol.skript.lang.Condition;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CondIsFurniture extends Condition {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerCondition(CondIsFurniture.class,
|
||||
"%entities% (is|are) furniture",
|
||||
"%entities% (is|are)(n't| not) furniture");
|
||||
}
|
||||
|
||||
private Expression<Entity> entities;
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
return entities.check(event, CraftEngineFurniture::isFurniture, isNegated());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return PropertyCondition.toString(this, PropertyCondition.PropertyType.BE, event, debug, entities, "furniture");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
entities = (Expression<Entity>) expressions[0];
|
||||
setNegated(matchedPattern > 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.effect;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Effect;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.skript.util.Direction;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class EffPlaceCustomBlock extends Effect {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEffect(EffPlaceCustomBlock.class, "place custom block %customblockstates% [%directions% %locations%]");
|
||||
}
|
||||
|
||||
private Expression<ImmutableBlockState> blocks;
|
||||
private Expression<Location> locations;
|
||||
|
||||
@Override
|
||||
protected void execute(Event e) {
|
||||
ImmutableBlockState[] os = blocks.getArray(e);
|
||||
for (Location l : locations.getArray(e)) {
|
||||
for (ImmutableBlockState o : os) {
|
||||
CraftEngineBlocks.place(l, o, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return "place custom block " + blocks.toString(event, debug) + " " + locations.toString(event, debug);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
blocks = (Expression<ImmutableBlockState>) expressions[0];
|
||||
locations = Direction.combine((Expression<? extends Direction>) expressions[1], (Expression<? extends Location>) expressions[2]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.effect;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Effect;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.skript.util.Direction;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class EffPlaceFurniture extends Effect {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEffect(EffPlaceFurniture.class, "place furniture %strings% [%directions% %locations%]");
|
||||
}
|
||||
|
||||
private Expression<String> furniture;
|
||||
private Expression<Location> locations;
|
||||
|
||||
@Override
|
||||
protected void execute(Event e) {
|
||||
String[] os = furniture.getArray(e);
|
||||
for (Location l : locations.getArray(e)) {
|
||||
for (String o : os) {
|
||||
CraftEngineFurniture.place(l, Key.of(o));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return "place furniture " + furniture.toString(event, debug) + " " + locations.toString(event, debug);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
furniture = (Expression<String>) expressions[0];
|
||||
locations = Direction.combine((Expression<? extends Direction>) expressions[1], (Expression<? extends Location>) expressions[2]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.effect;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Effect;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class EffRemoveFurniture extends Effect {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEffect(EffRemoveFurniture.class, "remove furniture %entities%");
|
||||
}
|
||||
|
||||
private Expression<Entity> entities;
|
||||
|
||||
@Override
|
||||
protected void execute(Event e) {
|
||||
for (Entity entity : entities.getArray(e)) {
|
||||
if (CraftEngineFurniture.isFurniture(entity)) {
|
||||
LoadedFurniture loadedFurniture = CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity);
|
||||
if (loadedFurniture != null) {
|
||||
loadedFurniture.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return "remove furniture " + entities.toString(event, debug);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
this.entities = (Expression<Entity>) expressions[0];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.event;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Literal;
|
||||
import ch.njol.skript.lang.SkriptEvent;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockPlaceEvent;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UnsafeBlockStateMatcher;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
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%]")
|
||||
.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%]")
|
||||
.description("Called when a player places a custom block.");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Literal<UnsafeBlockStateMatcher> blocks;
|
||||
private UnsafeBlockStateMatcher[] blockArray;
|
||||
private boolean mine = false;
|
||||
|
||||
@Override
|
||||
public boolean init(Literal<?>[] args, int matchedPattern, SkriptParser.ParseResult parser) {
|
||||
if (args[0] != null) {
|
||||
blocks = ((Literal<UnsafeBlockStateMatcher>) args[0]);
|
||||
blockArray = blocks.getAll();
|
||||
}
|
||||
mine = parser.mark == 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
if (mine && event instanceof CustomBlockBreakEvent customBlockBreakEvent) {
|
||||
if (!BlockStateUtils.isCorrectTool(customBlockBreakEvent.blockState(), customBlockBreakEvent.player().getItemInHand(InteractionHand.MAIN_HAND))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (blocks == null)
|
||||
return true;
|
||||
|
||||
ImmutableBlockState state;
|
||||
if (event instanceof CustomBlockBreakEvent customBlockBreakEvent) {
|
||||
state = customBlockBreakEvent.blockState();
|
||||
} else if (event instanceof CustomBlockPlaceEvent customBlockPlaceEvent) {
|
||||
state = customBlockPlaceEvent.blockState();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Arrays.stream(blockArray).anyMatch(block -> block.matches(state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return "break/place" + (blocks != null ? " of " + blocks.toString(event, debug) : "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.event;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.aliases.ItemType;
|
||||
import ch.njol.skript.bukkitutil.ClickEventTracker;
|
||||
import ch.njol.skript.lang.Literal;
|
||||
import ch.njol.skript.lang.SkriptEvent;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockInteractEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UnsafeBlockStateMatcher;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class EvtCustomClick extends SkriptEvent {
|
||||
|
||||
private final static int RIGHT = 1, LEFT = 2, ANY = RIGHT | LEFT;
|
||||
public final static ClickEventTracker interactTracker = new ClickEventTracker(Skript.getInstance());
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEvent("Interact Custom Block Furniture", EvtCustomClick.class, new Class[]{CustomBlockInteractEvent.class, FurnitureInteractEvent.class},
|
||||
"[(" + RIGHT + ":right|" + LEFT + ":left)(| |-)][mouse(| |-)]click[ing] [on %-unsafeblockstatematchers/strings%] [(with|using|holding) %-itemtype%]",
|
||||
"[(" + RIGHT + ":right|" + LEFT + ":left)(| |-)][mouse(| |-)]click[ing] (with|using|holding) %itemtype% on %unsafeblockstatematchers/strings%");
|
||||
}
|
||||
|
||||
private @Nullable Literal<?> type;
|
||||
private @Nullable Literal<ItemType> tools;
|
||||
private int click = ANY;
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
ImmutableBlockState block;
|
||||
String furnitureId;
|
||||
if (event instanceof CustomBlockInteractEvent interactEvent) {
|
||||
furnitureId = null;
|
||||
CustomBlockInteractEvent.Action action = interactEvent.action();
|
||||
int click;
|
||||
switch (action) {
|
||||
case LEFT_CLICK -> click = LEFT;
|
||||
case RIGHT_CLICK -> click = RIGHT;
|
||||
default -> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ((this.click & click) == 0)
|
||||
return false;
|
||||
EquipmentSlot hand = interactEvent.hand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND;
|
||||
if (!interactTracker.checkEvent(interactEvent.getPlayer(), interactEvent, hand)) {
|
||||
return false;
|
||||
}
|
||||
block = interactEvent.blockState();
|
||||
} else if (event instanceof FurnitureInteractEvent interactEvent) {
|
||||
furnitureId = interactEvent.furniture().id().toString();
|
||||
block = null;
|
||||
if ((this.click & RIGHT) == 0)
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
Predicate<ItemType> checker = itemType -> {
|
||||
if (event instanceof CustomBlockInteractEvent event1) {
|
||||
return itemType.isOfType(event1.item());
|
||||
} else if (event instanceof FurnitureInteractEvent event1) {
|
||||
return itemType.isOfType(event1.player().getInventory().getItem(event1.hand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (tools != null && !tools.check(event, checker))
|
||||
return false;
|
||||
|
||||
if (type != null) {
|
||||
return type.check(event, (Predicate<Object>) object -> {
|
||||
if (object instanceof String id && furnitureId != null) {
|
||||
return id.equals(furnitureId);
|
||||
} else if (object instanceof UnsafeBlockStateMatcher matcher && block != null) {
|
||||
return matcher.matches(block);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean init(Literal<?>[] args, int matchedPattern, SkriptParser.ParseResult parseResult) {
|
||||
click = parseResult.mark == 0 ? ANY : parseResult.mark;
|
||||
type = args[matchedPattern];
|
||||
tools = (Literal<ItemType>) args[1 - matchedPattern];
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return switch (click) {
|
||||
case LEFT -> "left";
|
||||
case RIGHT -> "right";
|
||||
default -> "";
|
||||
} + "click" + (type != null ? " on " + type.toString(event, debug) : "") +
|
||||
(tools != null ? " holding " + tools.toString(event, debug) : "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.event;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Literal;
|
||||
import ch.njol.skript.lang.SkriptEvent;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurniturePlaceEvent;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public class EvtCustomFurniture extends SkriptEvent {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerEvent("Break Furniture", EvtCustomFurniture.class, FurnitureBreakEvent.class, "(break[ing]) [[of] %-strings%]")
|
||||
.description("Called when a furniture is broken by a player.");
|
||||
Skript.registerEvent("Place Furniture", EvtCustomFurniture.class, FurniturePlaceEvent.class, "(plac(e|ing)|build[ing]) [[of] %-strings%]")
|
||||
.description("Called when a player places a furniture.");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Literal<String> ids;
|
||||
private String[] idArray;
|
||||
|
||||
@Override
|
||||
public boolean init(Literal<?>[] args, int matchedPattern, SkriptParser.ParseResult parser) {
|
||||
if (args[0] != null) {
|
||||
ids = ((Literal<String>) args[0]);
|
||||
idArray = ids.getAll();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(Event event) {
|
||||
if (ids == null)
|
||||
return true;
|
||||
|
||||
String id;
|
||||
if (event instanceof FurnitureBreakEvent e) {
|
||||
id = e.furniture().id().toString();
|
||||
} else if (event instanceof FurniturePlaceEvent e) {
|
||||
id = e.furniture().id().toString();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Arrays.asList(idArray).contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event event, boolean debug) {
|
||||
return "break/place" + (ids != null ? " of " + ids.toString(event, debug) : "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.expressions.base.SimplePropertyExpression;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String convert(Object object) {
|
||||
if (object instanceof ImmutableBlockState immutableBlockState)
|
||||
return immutableBlockState.owner().value().id().toString();
|
||||
if (object instanceof CustomBlock customBlock)
|
||||
return customBlock.id().toString();
|
||||
if (object instanceof Block block)
|
||||
return Optional.ofNullable(CraftEngineBlocks.getCustomBlockState(block)).map(it -> it.owner().value().id().toString()).orElse(null);
|
||||
if (object instanceof BlockData blockData)
|
||||
return Optional.ofNullable(CraftEngineBlocks.getCustomBlockState(blockData)).map(it -> it.owner().value().id().toString()).orElse(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyName() {
|
||||
return "custom block id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends String> getReturnType() {
|
||||
return String.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.expressions.base.SimplePropertyExpression;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
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");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ImmutableBlockState convert(Object object) {
|
||||
if (object instanceof Block block)
|
||||
return CraftEngineBlocks.getCustomBlockState(block);
|
||||
if (object instanceof BlockData blockData)
|
||||
return CraftEngineBlocks.getCustomBlockState(blockData);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyName() {
|
||||
return "custom block state";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ImmutableBlockState> getReturnType() {
|
||||
return ImmutableBlockState.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.Skript;
|
||||
import ch.njol.skript.lang.Expression;
|
||||
import ch.njol.skript.lang.ExpressionType;
|
||||
import ch.njol.skript.lang.SkriptParser;
|
||||
import ch.njol.skript.lang.util.SimpleExpression;
|
||||
import ch.njol.util.Kleenean;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ExprCustomItem extends SimpleExpression<ItemStack> {
|
||||
|
||||
public static void register() {
|
||||
Skript.registerExpression(ExprCustomItem.class, ItemStack.class, ExpressionType.SIMPLE, "[(the|a)] custom item [with id] %string%");
|
||||
}
|
||||
|
||||
private Expression<String> itemId;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
|
||||
itemId = (Expression<String>) exprs[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemStack[] get(Event e) {
|
||||
String itemId = this.itemId.getSingle(e);
|
||||
if (itemId == null)
|
||||
return null;
|
||||
return new ItemStack[] {Objects.requireNonNull(CraftEngineItems.byId(Key.of(itemId))).buildItemStack(ItemBuildContext.EMPTY)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ItemStack> getReturnType() {
|
||||
return ItemStack.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(@Nullable Event e, boolean debug) {
|
||||
return "the custom item with id " + itemId.toString(e, debug);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.expressions.base.SimplePropertyExpression;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ExprEntityFurnitureID extends SimplePropertyExpression<Object, String> {
|
||||
|
||||
public static void register() {
|
||||
register(ExprEntityFurnitureID.class, String.class, "furniture id", "entities");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String convert(Object object) {
|
||||
if (object instanceof Entity entity && CraftEngineFurniture.isFurniture(entity))
|
||||
return Objects.requireNonNull(CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity)).id().toString();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyName() {
|
||||
return "furniture id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends String> getReturnType() {
|
||||
return String.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.skript.expression;
|
||||
|
||||
import ch.njol.skript.aliases.ItemType;
|
||||
import ch.njol.skript.classes.Changer;
|
||||
import ch.njol.skript.expressions.base.SimplePropertyExpression;
|
||||
import ch.njol.util.coll.CollectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ExprItemCustomItemID extends SimplePropertyExpression<Object, String> {
|
||||
|
||||
public static void register() {
|
||||
register(ExprItemCustomItemID.class, String.class, "custom item id", "itemstacks/itemtypes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String convert(Object object) {
|
||||
if (object instanceof ItemStack itemStack)
|
||||
return Optional.ofNullable(CraftEngineItems.byItemStack(itemStack)).map(it -> it.id().toString()).orElse(null);
|
||||
if (object instanceof ItemType itemType) {
|
||||
ItemStack itemStack = new ItemStack(itemType.getMaterial());
|
||||
itemStack.setItemMeta(itemType.getItemMeta());
|
||||
return Optional.ofNullable(CraftEngineItems.byItemStack(itemStack)).map(it -> it.id().toString()).orElse(null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyName() {
|
||||
return "custom item id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends String> getReturnType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] acceptChange(Changer.ChangeMode mode) {
|
||||
return CollectionUtils.array(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void change(Event e, @Nullable Object[] delta, Changer.ChangeMode mode) {
|
||||
Key id = Key.of((String) delta[0]);
|
||||
for (Object item : getExpr().getArray(e)) {
|
||||
if (item instanceof ItemStack itemStack) {
|
||||
Item<ItemStack> item1 = BukkitItemManager.instance().wrap(itemStack);
|
||||
Item<ItemStack> item2 = BukkitItemManager.instance().createWrappedItem(id, null);
|
||||
item1.merge(item2);
|
||||
item1.load();
|
||||
} else if (item instanceof ItemType itemType) {
|
||||
Item<ItemStack> item2 = BukkitItemManager.instance().createWrappedItem(id, null);
|
||||
itemType.setItemMeta(item2.load().getItemMeta());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,15 @@ package net.momirealms.craftengine.bukkit.compatibility.slimeworld;
|
||||
|
||||
import com.infernalsuite.asp.api.world.SlimeChunk;
|
||||
import com.infernalsuite.asp.api.world.SlimeWorld;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||
import net.momirealms.craftengine.core.world.chunk.serialization.DefaultChunkSerializer;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.NBT;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -25,15 +27,16 @@ public class SlimeWorldDataStorage implements WorldDataStorage {
|
||||
return slimeWorld.get();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CompoundTag readChunkTagAt(ChunkPos pos) {
|
||||
public @NotNull CEChunk readChunkAt(@NotNull CEWorld world, @NotNull ChunkPos pos) {
|
||||
SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z);
|
||||
if (slimeChunk == null) return null;
|
||||
if (slimeChunk == null) return new CEChunk(world, pos);
|
||||
Object tag = slimeChunk.getExtraData().get("craftengine");
|
||||
if (tag == null) return null;
|
||||
if (tag == null) return new CEChunk(world, pos);
|
||||
try {
|
||||
return NBT.fromBytes(adaptor.byteArrayTagToBytes(tag));
|
||||
CompoundTag compoundTag = NBT.fromBytes(adaptor.byteArrayTagToBytes(tag));
|
||||
if (compoundTag == null) return new CEChunk(world, pos);
|
||||
return DefaultChunkSerializer.deserialize(world, pos, compoundTag);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to read chunk tag from slime world. " + pos, e);
|
||||
}
|
||||
@@ -41,9 +44,10 @@ public class SlimeWorldDataStorage implements WorldDataStorage {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void writeChunkTagAt(ChunkPos pos, @Nullable CompoundTag nbt) {
|
||||
public void writeChunkAt(@NotNull ChunkPos pos, @NotNull CEChunk chunk, boolean immediately) {
|
||||
SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z);
|
||||
if (slimeChunk == null) return;
|
||||
CompoundTag nbt = DefaultChunkSerializer.serialize(chunk);
|
||||
if (nbt == null) {
|
||||
slimeChunk.getExtraData().remove("craftengine");
|
||||
} else {
|
||||
@@ -63,6 +67,6 @@ public class SlimeWorldDataStorage implements WorldDataStorage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ViaVersionUtils {
|
||||
|
||||
private ViaVersionUtils() {}
|
||||
|
||||
public static int getPlayerProtocolVersion(UUID uuid) {
|
||||
return Via.getAPI().getPlayerProtocolVersion(uuid).getVersion();
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public class WorldEditBlockRegister {
|
||||
private final boolean isFAWE;
|
||||
|
||||
public WorldEditBlockRegister(AbstractBlockManager manager, boolean isFAWE) {
|
||||
field$BlockType$blockMaterial = ReflectionUtils.getDeclaredField(BlockType.class, "blockMaterial");
|
||||
this.field$BlockType$blockMaterial = ReflectionUtils.getDeclaredField(BlockType.class, "blockMaterial");
|
||||
this.manager = manager;
|
||||
this.isFAWE = isFAWE;
|
||||
CEBlockParser blockParser = new CEBlockParser(WorldEdit.getInstance());
|
||||
@@ -34,7 +34,7 @@ public class WorldEditBlockRegister {
|
||||
|
||||
public void register(Key id) throws ReflectiveOperationException {
|
||||
BlockType blockType = new BlockType(id.toString(), blockState -> blockState);
|
||||
field$BlockType$blockMaterial.set(blockType, LazyReference.from(() -> new BukkitBlockRegistry.BukkitBlockMaterial(null, Material.STONE)));
|
||||
this.field$BlockType$blockMaterial.set(blockType, LazyReference.from(() -> new BukkitBlockRegistry.BukkitBlockMaterial(null, Material.STONE)));
|
||||
BlockType.REGISTRY.register(id.toString(), blockType);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ dependencies {
|
||||
implementation(project(":bukkit"))
|
||||
implementation(project(":bukkit:legacy"))
|
||||
implementation(project(":bukkit:compatibility"))
|
||||
implementation(project(":bukkit:compatibility:legacy"))
|
||||
|
||||
implementation("net.kyori:adventure-platform-bukkit:${rootProject.properties["adventure_platform_version"]}")
|
||||
implementation("com.saicone.rtag:rtag-item:${rootProject.properties["rtag_version"]}")
|
||||
@@ -49,7 +50,7 @@ bukkit {
|
||||
apiVersion = "1.20"
|
||||
authors = listOf("XiaoMoMi")
|
||||
contributors = listOf("jhqwqmc", "iqtesterrr")
|
||||
softDepend = listOf("PlaceholderAPI", "WorldEdit", "FastAsyncWorldEdit")
|
||||
softDepend = listOf("PlaceholderAPI", "WorldEdit", "FastAsyncWorldEdit", "Skript")
|
||||
foliaSupported = true
|
||||
}
|
||||
|
||||
|
||||
@@ -343,6 +343,8 @@ light-system:
|
||||
force-update-light: false
|
||||
|
||||
chunk-system:
|
||||
# Unloaded chunks may be loaded soon. Delaying serialization can improve performance, especially for those double-dimension mob farms.
|
||||
delay-serialization: 20 # seconds -1 = disable
|
||||
# 1 = NONE | Compression Speed | Decompress Speed | Compression Ratio | Memory Usage |
|
||||
# 2 = DEFLATE | Medium-Slow Medium Moderate Low |
|
||||
# 3 = GZIP | Medium-Slow Medium Moderate Low |
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package net.momirealms.craftengine.bukkit.api;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldBlock;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public final class BukkitAdaptors {
|
||||
|
||||
private BukkitAdaptors() {}
|
||||
|
||||
public static BukkitServerPlayer adapt(final Player player) {
|
||||
return BukkitCraftEngine.instance().adapt(player);
|
||||
}
|
||||
|
||||
public static BukkitWorld adapt(final World world) {
|
||||
return new BukkitWorld(world);
|
||||
}
|
||||
|
||||
public static BukkitEntity adapt(final Entity entity) {
|
||||
return new BukkitEntity(entity);
|
||||
}
|
||||
|
||||
public static BukkitWorldBlock adapt(final Block block) {
|
||||
return new BukkitWorldBlock(block);
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class CraftEngineBlocks {
|
||||
|
||||
private CraftEngineBlocks() {}
|
||||
|
||||
/**
|
||||
* Gets a custom block by ID
|
||||
*
|
||||
@@ -122,7 +124,7 @@ public final class CraftEngineBlocks {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a block from the world if it's a custom one
|
||||
* Removes a block from the world if it's custom
|
||||
*
|
||||
* @param block block to remove
|
||||
* @return success or not
|
||||
@@ -134,7 +136,7 @@ public final class CraftEngineBlocks {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a block from the world if it's a custom one
|
||||
* Removes a block from the world if it's custom
|
||||
*
|
||||
* @param block block to remove
|
||||
* @param applyPhysics whether to apply physics
|
||||
@@ -148,7 +150,7 @@ public final class CraftEngineBlocks {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a block from the world if it's a custom one
|
||||
* Removes a block from the world if it's custom
|
||||
*
|
||||
* @param block block to remove
|
||||
* @param player player who breaks the block
|
||||
@@ -191,7 +193,7 @@ public final class CraftEngineBlocks {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a block is a custom one
|
||||
* Checks if a block is custom
|
||||
*
|
||||
* @param block block
|
||||
* @return is custom block or not
|
||||
@@ -234,7 +236,7 @@ public final class CraftEngineBlocks {
|
||||
* @return bukkit block data
|
||||
*/
|
||||
@NotNull
|
||||
public static BlockData createBukkitBlockData(@NotNull ImmutableBlockState blockState) {
|
||||
public static BlockData getBukkitBlockData(@NotNull ImmutableBlockState blockState) {
|
||||
return BlockStateUtils.fromBlockData(blockState.customBlockState().handle());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package net.momirealms.craftengine.bukkit.api;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture;
|
||||
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.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
@@ -25,7 +27,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CraftEngineFurniture {
|
||||
public final class CraftEngineFurniture {
|
||||
|
||||
private CraftEngineFurniture() {}
|
||||
|
||||
/**
|
||||
* Gets custom furniture by ID
|
||||
@@ -120,6 +124,17 @@ public class CraftEngineFurniture {
|
||||
return furnitureId != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an entity is a collision entity
|
||||
*
|
||||
* @param entity entity to check
|
||||
* @return is collision entity or not
|
||||
*/
|
||||
public static boolean isCollisionEntity(@NotNull Entity entity) {
|
||||
Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(entity);
|
||||
return nmsEntity instanceof CollisionEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an entity is a seat
|
||||
*
|
||||
|
||||
@@ -8,7 +8,9 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CraftEngineItems {
|
||||
public final class CraftEngineItems {
|
||||
|
||||
private CraftEngineItems() {}
|
||||
|
||||
/**
|
||||
* Gets a custom item by ID
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package net.momirealms.craftengine.bukkit.api.event;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
@@ -18,17 +18,23 @@ public class CustomBlockBreakEvent extends PlayerEvent implements Cancellable {
|
||||
private final Location location;
|
||||
private final Block bukkitBlock;
|
||||
private boolean dropItems;
|
||||
private final BukkitServerPlayer player;
|
||||
|
||||
public CustomBlockBreakEvent(@NotNull Player player,
|
||||
public CustomBlockBreakEvent(@NotNull BukkitServerPlayer player,
|
||||
@NotNull Location location,
|
||||
@NotNull Block bukkitBlock,
|
||||
@NotNull ImmutableBlockState state) {
|
||||
super(player);
|
||||
super(player.platformPlayer());
|
||||
this.customBlock = state.owner().value();
|
||||
this.state = state;
|
||||
this.bukkitBlock = bukkitBlock;
|
||||
this.location = location;
|
||||
this.dropItems = true;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public BukkitServerPlayer player() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public boolean dropItems() {
|
||||
@@ -44,11 +50,6 @@ public class CustomBlockBreakEvent extends PlayerEvent implements Cancellable {
|
||||
return bukkitBlock;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Player player() {
|
||||
return getPlayer();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CustomBlock customBlock() {
|
||||
return this.customBlock;
|
||||
|
||||
@@ -10,6 +10,8 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -24,6 +26,7 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable
|
||||
private final InteractionHand hand;
|
||||
private final Action action;
|
||||
private final BlockFace clickedFace;
|
||||
private final ItemStack item;
|
||||
|
||||
public CustomBlockInteractEvent(@NotNull Player player,
|
||||
@NotNull Location location,
|
||||
@@ -32,7 +35,8 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable
|
||||
@NotNull Block bukkitBlock,
|
||||
@NotNull BlockFace clickedFace,
|
||||
@NotNull InteractionHand hand,
|
||||
@NotNull Action action) {
|
||||
@NotNull Action action,
|
||||
@Nullable ItemStack item) {
|
||||
super(player);
|
||||
this.customBlock = state.owner().value();
|
||||
this.bukkitBlock = bukkitBlock;
|
||||
@@ -42,6 +46,7 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable
|
||||
this.hand = hand;
|
||||
this.action = action;
|
||||
this.clickedFace = clickedFace;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -89,6 +94,12 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable
|
||||
return this.state;
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
@NotNull
|
||||
public ItemStack item() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
|
||||
@@ -7,7 +7,6 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
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.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
@@ -52,7 +51,7 @@ public class BlockEventListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlayerAttack(EntityDamageByEntityEvent event) {
|
||||
if (!VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
if (!VersionHelper.isOrAbove1_20_5()) {
|
||||
if (event.getDamager() instanceof Player player) {
|
||||
BukkitServerPlayer serverPlayer = plugin.adapt(player);
|
||||
serverPlayer.setClientSideCanBreakBlock(true);
|
||||
@@ -120,7 +119,7 @@ public class BlockEventListener implements Listener {
|
||||
}
|
||||
|
||||
// trigger event
|
||||
CustomBlockBreakEvent customBreakEvent = new CustomBlockBreakEvent(event.getPlayer(), location, block, state);
|
||||
CustomBlockBreakEvent customBreakEvent = new CustomBlockBreakEvent(serverPlayer, location, block, state);
|
||||
boolean isCancelled = EventUtils.fireAndCheckCancel(customBreakEvent);
|
||||
if (isCancelled) {
|
||||
event.setCancelled(true);
|
||||
@@ -146,14 +145,10 @@ public class BlockEventListener implements Listener {
|
||||
|
||||
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
// do not drop if it's not the correct tool
|
||||
BlockSettings settings = state.settings();
|
||||
if (settings.requireCorrectTool()) {
|
||||
if (itemInHand == null) return;
|
||||
if (!settings.isCorrectTool(itemInHand.id()) &&
|
||||
(!settings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(itemInHand.getLiteralObject(), state.customBlockState().handle()))) {
|
||||
return;
|
||||
}
|
||||
if (!BlockStateUtils.isCorrectTool(state, itemInHand)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// drop items
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
@@ -311,7 +306,7 @@ public class BlockEventListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onEntityExplode(EntityExplodeEvent event) {
|
||||
if (VersionHelper.isVersionNewerThan1_21()) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
if (!ExplosionUtils.isDroppingItems(event)) return;
|
||||
}
|
||||
handleExplodeEvent(event.blockList(), new BukkitWorld(event.getEntity().getWorld()), event.getYield());
|
||||
@@ -319,7 +314,7 @@ public class BlockEventListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onBlockExplode(BlockExplodeEvent event) {
|
||||
if (VersionHelper.isVersionNewerThan1_21()) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
if (!ExplosionUtils.isDroppingItems(event)) return;
|
||||
}
|
||||
handleExplodeEvent(event.blockList(), new BukkitWorld(event.getBlock().getWorld()), event.getYield());
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import dev.dejvokep.boostedyaml.YamlDocument;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.worldedit.WorldEditBlockRegister;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
|
||||
@@ -108,7 +107,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
if (enableNoteBlocks) {
|
||||
this.recordVanillaNoteBlocks();
|
||||
}
|
||||
if (VersionHelper.isVersionNewerThan1_20_3()) {
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
this.fallingBlockRemoveListener = new FallingBlockRemoveListener();
|
||||
} else this.fallingBlockRemoveListener = null;
|
||||
this.stateId2ImmutableBlockStates = new ImmutableBlockState[customBlockCount];
|
||||
@@ -117,6 +116,10 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
this.resetPacketConsumers();
|
||||
}
|
||||
|
||||
public List<Key> blockRegisterOrder() {
|
||||
return Collections.unmodifiableList(this.blockRegisterOrder);
|
||||
}
|
||||
|
||||
public static BukkitBlockManager instance() {
|
||||
return instance;
|
||||
}
|
||||
@@ -127,12 +130,6 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
if (this.fallingBlockRemoveListener != null) {
|
||||
Bukkit.getPluginManager().registerEvents(this.fallingBlockRemoveListener, plugin.bootstrap());
|
||||
}
|
||||
// WorldEdit
|
||||
if (this.plugin.isPluginEnabled("FastAsyncWorldEdit")) {
|
||||
this.initFastAsyncWorldEditHook();
|
||||
} else if (this.plugin.isPluginEnabled("WorldEdit")) {
|
||||
this.initWorldEditHook();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -171,20 +168,6 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
this.tempVanillaBlockStateModels.clear();
|
||||
}
|
||||
|
||||
public void initFastAsyncWorldEditHook() {
|
||||
new WorldEditBlockRegister(this, true);
|
||||
}
|
||||
|
||||
public void initWorldEditHook() {
|
||||
WorldEditBlockRegister weBlockRegister = new WorldEditBlockRegister(this, false);
|
||||
try {
|
||||
for (Key newBlockId : this.blockRegisterOrder) {
|
||||
weBlockRegister.register(newBlockId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to initialize world edit hook", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object getMinecraftBlockHolder(int stateId) {
|
||||
|
||||
@@ -107,7 +107,7 @@ public class BukkitCustomBlock extends CustomBlock {
|
||||
Reflections.method$BlockStateBase$initCache.invoke(mcBlockState);
|
||||
// set block light
|
||||
if (settings.blockLight() != -1) {
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
Reflections.field$BlockStateBase$lightBlock.set(mcBlockState, settings.blockLight());
|
||||
} else {
|
||||
Object cache = Reflections.field$BlockStateBase$cache.get(mcBlockState);
|
||||
|
||||
@@ -56,7 +56,7 @@ public class BushBlockBehavior extends BukkitBlockBehavior {
|
||||
Object level;
|
||||
Object blockPos;
|
||||
Object state = args[0];
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
level = args[1];
|
||||
blockPos = args[3];
|
||||
} else {
|
||||
|
||||
@@ -99,7 +99,7 @@ public class ConcretePowderBlockBehavior extends FallingBlockBehavior {
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object level;
|
||||
Object pos;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
level = args[1];
|
||||
pos = args[3];
|
||||
} else {
|
||||
|
||||
@@ -42,7 +42,7 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object world;
|
||||
Object blockPos;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
world = args[1];
|
||||
blockPos = args[3];
|
||||
} else {
|
||||
@@ -81,7 +81,7 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public void onBrokenAfterFall(Object thisBlock, Object[] args) throws Exception {
|
||||
// Use EntityRemoveEvent for 1.20.3+
|
||||
if (VersionHelper.isVersionNewerThan1_20_3()) return;
|
||||
if (VersionHelper.isOrAbove1_20_3()) return;
|
||||
Object level = args[0];
|
||||
Object fallingBlockEntity = args[2];
|
||||
boolean cancelDrop = (boolean) Reflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity);
|
||||
|
||||
@@ -66,7 +66,7 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
Object blockPos;
|
||||
Object neighborState;
|
||||
Object blockState = args[0];
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
world = args[1];
|
||||
neighborState = args[6];
|
||||
blockPos = args[3];
|
||||
|
||||
@@ -79,7 +79,7 @@ public class SugarCaneBlockBehavior extends BushBlockBehavior {
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object world;
|
||||
Object blockPos;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
world = args[1];
|
||||
blockPos = args[3];
|
||||
} else {
|
||||
@@ -120,7 +120,7 @@ public class SugarCaneBlockBehavior extends BushBlockBehavior {
|
||||
int age = currentState.get(ageProperty);
|
||||
if (age >= this.ageProperty.max || RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) {
|
||||
Object abovePos = LocationUtils.above(blockPos);
|
||||
if (VersionHelper.isVersionNewerThan1_21_5()) {
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, super.customBlock.defaultState().customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
} else {
|
||||
Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, super.customBlock.defaultState().customBlockState().handle());
|
||||
|
||||
@@ -38,6 +38,6 @@ public class DisplayEntityData<T> extends BaseEntityData<T> {
|
||||
}
|
||||
|
||||
public DisplayEntityData(int id, Object serializer, T defaultValue) {
|
||||
super(!VersionHelper.isVersionNewerThan1_20_2() && id >= 11 ? id - 1 : id, serializer, defaultValue);
|
||||
super(!VersionHelper.isOrAbove1_20_2() && id >= 11 ? id - 1 : id, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,15 +60,15 @@ public class EntityDataValue {
|
||||
Serializers$OPTIONAL_BLOCK_STATE = initSerializersByName("OPTIONAL_BLOCK_STATE");
|
||||
Serializers$BOOLEAN = initSerializersByName("BOOLEAN");
|
||||
Serializers$PARTICLE = initSerializersByName("PARTICLE");
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) Serializers$PARTICLES = initSerializersByName("PARTICLES");
|
||||
if (VersionHelper.isOrAbove1_20_5()) Serializers$PARTICLES = initSerializersByName("PARTICLES");
|
||||
else Serializers$PARTICLES = null;
|
||||
Serializers$ROTATIONS = initSerializersByName("ROTATIONS");
|
||||
Serializers$BLOCK_POS = initSerializersByName("BLOCK_POS");
|
||||
Serializers$OPTIONAL_BLOCK_POS = initSerializersByName("OPTIONAL_BLOCK_POS");
|
||||
Serializers$DIRECTION = initSerializersByName("DIRECTION");
|
||||
if (!VersionHelper.isVersionNewerThan1_21_5()) Serializers$OPTIONAL_UUID = initSerializersByName("OPTIONAL_UUID");
|
||||
if (!VersionHelper.isOrAbove1_21_5()) Serializers$OPTIONAL_UUID = initSerializersByName("OPTIONAL_UUID");
|
||||
else Serializers$OPTIONAL_UUID = null;
|
||||
if (VersionHelper.isVersionNewerThan1_21_5()) Serializers$OPTIONAL_LIVING_ENTITY_REFERENCE = initSerializersByName("OPTIONAL_LIVING_ENTITY_REFERENCE");
|
||||
if (VersionHelper.isOrAbove1_21_5()) Serializers$OPTIONAL_LIVING_ENTITY_REFERENCE = initSerializersByName("OPTIONAL_LIVING_ENTITY_REFERENCE");
|
||||
else Serializers$OPTIONAL_LIVING_ENTITY_REFERENCE = null;
|
||||
Serializers$OPTIONAL_GLOBAL_POS = initSerializersByName("OPTIONAL_GLOBAL_POS");
|
||||
Serializers$COMPOUND_TAG = initSerializersByName("COMPOUND_TAG");
|
||||
@@ -76,11 +76,11 @@ public class EntityDataValue {
|
||||
Serializers$OPTIONAL_UNSIGNED_INT = initSerializersByName("OPTIONAL_UNSIGNED_INT");
|
||||
Serializers$POSE = initSerializersByName("POSE");
|
||||
Serializers$CAT_VARIANT = initSerializersByName("CAT_VARIANT");
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) Serializers$WOLF_VARIANT = initSerializersByName("WOLF_VARIANT");
|
||||
if (VersionHelper.isOrAbove1_20_5()) Serializers$WOLF_VARIANT = initSerializersByName("WOLF_VARIANT");
|
||||
else Serializers$WOLF_VARIANT = null;
|
||||
Serializers$FROG_VARIANT = initSerializersByName("FROG_VARIANT");
|
||||
Serializers$PAINTING_VARIANT = initSerializersByName("PAINTING_VARIANT");
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) Serializers$ARMADILLO_STATE = initSerializersByName("ARMADILLO_STATE");
|
||||
if (VersionHelper.isOrAbove1_20_5()) Serializers$ARMADILLO_STATE = initSerializersByName("ARMADILLO_STATE");
|
||||
else Serializers$ARMADILLO_STATE = null;
|
||||
Serializers$SNIFFER_STATE = initSerializersByName("SNIFFER_STATE");
|
||||
Serializers$VECTOR3 = initSerializersByName("VECTOR3");
|
||||
|
||||
@@ -13,6 +13,6 @@ public class InteractionEntityData<T> extends BaseEntityData<T> {
|
||||
}
|
||||
|
||||
public InteractionEntityData(int id, Object serializer, T defaultValue) {
|
||||
super(!VersionHelper.isVersionNewerThan1_20_2() && id >= 11 ? id - 1 : id, serializer, defaultValue);
|
||||
super(!VersionHelper.isOrAbove1_20_2() && id >= 11 ? id - 1 : id, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.compatibility.bettermodel.BetterModelModel;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineModel;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitBox;
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
@@ -60,7 +58,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
this.plugin = plugin;
|
||||
this.furnitureParser = new FurnitureParser();
|
||||
this.furnitureEventListener = new FurnitureEventListener(this);
|
||||
this.dismountListener = VersionHelper.isVersionNewerThan1_20_3() ? new DismountListener1_20_3(this) : new DismountListener1_20(this::handleDismount);
|
||||
this.dismountListener = VersionHelper.isOrAbove1_20_3() ? new DismountListener1_20_3(this) : new DismountListener1_20(this::handleDismount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,9 +147,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
// external model providers
|
||||
Optional<ExternalModel> externalModel;
|
||||
if (placementArguments.containsKey("model-engine")) {
|
||||
externalModel = Optional.of(new ModelEngineModel(placementArguments.get("model-engine").toString()));
|
||||
externalModel = Optional.of(plugin.compatibilityManager().createModelEngineModel(placementArguments.get("model-engine").toString()));
|
||||
} else if (placementArguments.containsKey("better-model")) {
|
||||
externalModel = Optional.of(new BetterModelModel(placementArguments.get("better-model").toString()));
|
||||
externalModel = Optional.of(plugin.compatibilityManager().createBetterModelModel(placementArguments.get("better-model").toString()));
|
||||
} else {
|
||||
externalModel = Optional.empty();
|
||||
}
|
||||
@@ -294,7 +292,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
if (previous != null) return;
|
||||
|
||||
Location location = display.getLocation();
|
||||
boolean above1_20_1 = VersionHelper.isVersionNewerThan1_20_2();
|
||||
boolean above1_20_1 = VersionHelper.isOrAbove1_20_2();
|
||||
boolean preventChange = FastNMS.INSTANCE.isPreventingStatusUpdates(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
if (above1_20_1) {
|
||||
if (!preventChange) {
|
||||
@@ -453,7 +451,11 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
}
|
||||
targetLocation.setYaw(player.getLocation().getYaw());
|
||||
targetLocation.setPitch(player.getLocation().getPitch());
|
||||
player.teleport(targetLocation);
|
||||
if (VersionHelper.isFolia()) {
|
||||
player.teleportAsync(targetLocation);
|
||||
} else {
|
||||
player.teleport(targetLocation);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isSeatCarrierType(Entity entity) {
|
||||
|
||||
@@ -297,9 +297,9 @@ public class LoadedFurniture implements Furniture {
|
||||
public void spawnSeatEntityForPlayer(org.bukkit.entity.Player player, Seat seat) {
|
||||
Location location = this.calculateSeatLocation(seat);
|
||||
Entity seatEntity = seat.limitPlayerRotation() ?
|
||||
EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isVersionNewerThan1_20_2() ? location.subtract(0,0.9875,0) : location.subtract(0,0.990625,0), EntityType.ARMOR_STAND, entity -> {
|
||||
EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isOrAbove1_20_2() ? location.subtract(0,0.9875,0) : location.subtract(0,0.990625,0), EntityType.ARMOR_STAND, entity -> {
|
||||
ArmorStand armorStand = (ArmorStand) entity;
|
||||
if (VersionHelper.isVersionNewerThan1_21_3()) {
|
||||
if (VersionHelper.isOrAbove1_21_3()) {
|
||||
Objects.requireNonNull(armorStand.getAttribute(Attribute.MAX_HEALTH)).setBaseValue(0.01);
|
||||
} else {
|
||||
LegacyAttributeUtils.setMaxHealth(armorStand);
|
||||
@@ -316,7 +316,7 @@ public class LoadedFurniture implements Furniture {
|
||||
armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, this.baseEntityId());
|
||||
armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, seat.offset().x + ", " + seat.offset().y + ", " + seat.offset().z);
|
||||
}) :
|
||||
EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isVersionNewerThan1_20_2() ? location : location.subtract(0,0.25,0), EntityType.ITEM_DISPLAY, entity -> {
|
||||
EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isOrAbove1_20_2() ? location : location.subtract(0,0.25,0), EntityType.ITEM_DISPLAY, entity -> {
|
||||
ItemDisplay itemDisplay = (ItemDisplay) entity;
|
||||
itemDisplay.setPersistent(false);
|
||||
itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, this.baseEntityId());
|
||||
|
||||
@@ -57,7 +57,7 @@ public class CustomHitBox extends AbstractHitBox {
|
||||
FastNMS.INSTANCE.toNMSEntityType(this.entityType), 0, Reflections.instance$Vec3$Zero, 0
|
||||
), true);
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId[0], List.copyOf(this.cachedValues)), true);
|
||||
if (VersionHelper.isVersionNewerThan1_20_5() && this.scale != 1) {
|
||||
if (VersionHelper.isOrAbove1_20_5() && this.scale != 1) {
|
||||
Object attributeInstance = Reflections.constructor$AttributeInstance.newInstance(Reflections.instance$Holder$Attribute$scale, (Consumer<?>) (o) -> {});
|
||||
Reflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, this.scale);
|
||||
packets.accept(Reflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityId[0], Collections.singletonList(attributeInstance)), false);
|
||||
|
||||
@@ -223,7 +223,7 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
), false);
|
||||
}
|
||||
// set shulker scale
|
||||
if (VersionHelper.isVersionNewerThan1_20_5() && this.scale != 1) {
|
||||
if (VersionHelper.isOrAbove1_20_5() && this.scale != 1) {
|
||||
Object attributeInstance = Reflections.constructor$AttributeInstance.newInstance(Reflections.instance$Holder$Attribute$scale, (Consumer<?>) (o) -> {});
|
||||
Reflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, this.scale);
|
||||
packets.accept(Reflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityIds[1], Collections.singletonList(attributeInstance)), false);
|
||||
|
||||
@@ -5,7 +5,6 @@ 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.compatibility.permission.LuckPermsEventListeners;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils;
|
||||
@@ -35,7 +34,6 @@ import java.util.*;
|
||||
|
||||
public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
private final BukkitCraftEngine plugin;
|
||||
private LuckPermsEventListeners luckPermsEventListeners;
|
||||
|
||||
public BukkitFontManager(BukkitCraftEngine plugin) {
|
||||
super(plugin);
|
||||
@@ -44,9 +42,6 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
|
||||
@Override
|
||||
public void delayedInit() {
|
||||
if (this.plugin.isPluginEnabled("LuckPerms")) {
|
||||
luckPermsEventListeners = new LuckPermsEventListeners(plugin.bootstrap(), this::refreshEmojiSuggestions);
|
||||
}
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.bootstrap());
|
||||
}
|
||||
|
||||
@@ -54,9 +49,6 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
public void disable() {
|
||||
super.disable();
|
||||
HandlerList.unregisterAll(this);
|
||||
if (luckPermsEventListeners != null && this.plugin.isPluginEnabled("LuckPerms")) {
|
||||
luckPermsEventListeners.unregisterListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,7 +68,8 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
plugin.scheduler().async().execute(() -> this.addEmojiSuggestions(event.getPlayer(), getEmojiSuggestion(event.getPlayer())));
|
||||
}
|
||||
|
||||
private void refreshEmojiSuggestions(UUID uuid) {
|
||||
@Override
|
||||
public void refreshEmojiSuggestions(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player == null) return;
|
||||
removeEmojiSuggestions(player);
|
||||
@@ -138,14 +131,14 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
if (result == null) return;
|
||||
Player player;
|
||||
try {
|
||||
player = (Player) Reflections.method$InventoryView$getPlayer.invoke(VersionHelper.isVersionNewerThan1_21() ? event.getView() : LegacyInventoryUtils.getView(event));
|
||||
player = (Player) Reflections.method$InventoryView$getPlayer.invoke(VersionHelper.isOrAbove1_21() ? event.getView() : LegacyInventoryUtils.getView(event));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to get inventory viewer", e);
|
||||
return;
|
||||
}
|
||||
|
||||
String renameText;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
AnvilView anvilView = event.getView();
|
||||
renameText = anvilView.getRenameText();
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.item;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.compatibility.item.MMOItemsProvider;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsProvider;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BoneMealItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BucketItemBehavior;
|
||||
@@ -131,16 +129,6 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
public void delayedInit() {
|
||||
Bukkit.getPluginManager().registerEvents(this.itemEventListener, this.plugin.bootstrap());
|
||||
Bukkit.getPluginManager().registerEvents(this.debugStickListener, this.plugin.bootstrap());
|
||||
this.hookExternalPlugins();
|
||||
}
|
||||
|
||||
private void hookExternalPlugins() {
|
||||
if (this.plugin.isPluginEnabled("NeigeItems")) {
|
||||
registerExternalItemProvider(new NeigeItemsProvider());
|
||||
}
|
||||
if (this.plugin.isPluginEnabled("MMOItems")) {
|
||||
registerExternalItemProvider(new MMOItemsProvider());
|
||||
}
|
||||
}
|
||||
|
||||
public static BukkitItemManager instance() {
|
||||
@@ -289,7 +277,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
itemBuilder.dataModifier(new CustomModelDataModifier<>(customModelData));
|
||||
}
|
||||
// Requires the item to have model before apply item-model
|
||||
else if (!hasItemModelSection && section.containsKey("model") && VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
else if (!hasItemModelSection && section.containsKey("model") && VersionHelper.isOrAbove1_21_2()) {
|
||||
// check server version here because components require 1.21.2+
|
||||
// customize or use the id
|
||||
itemModelKey = Key.from(section.getOrDefault("item-model", id.toString()).toString());
|
||||
|
||||
@@ -22,6 +22,10 @@ public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
|
||||
this.item.setAmount(count);
|
||||
}
|
||||
|
||||
public void removeComponent(Object type) {
|
||||
FastNMS.INSTANCE.removeComponent(this.getLiteralObject(), ensureDataComponentType(type));
|
||||
}
|
||||
|
||||
public void resetComponent(Object type) {
|
||||
FastNMS.INSTANCE.resetComponent(this.getLiteralObject(), ensureDataComponentType(type));
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class ComponentTypes {
|
||||
private ComponentTypes() {}
|
||||
|
||||
private static Object getComponentType(Key key) {
|
||||
if (!VersionHelper.isVersionNewerThan1_20_5()) return null;
|
||||
if (!VersionHelper.isOrAbove1_20_5()) return null;
|
||||
return FastNMS.INSTANCE.getComponentType(key.namespace(), key.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,8 @@ public class ItemEventListener implements Listener {
|
||||
block,
|
||||
event.getBlockFace(),
|
||||
event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND,
|
||||
action.isRightClick() ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK
|
||||
action.isRightClick() ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK,
|
||||
event.getItem()
|
||||
);
|
||||
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
||||
event.setCancelled(true);
|
||||
|
||||
@@ -96,7 +96,7 @@ public class AxeItemBehavior extends ItemBehavior {
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
// shrink item amount
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
Object itemStack = item.getLiteralObject();
|
||||
Object serverPlayer = player.serverPlayer();
|
||||
Object equipmentSlot = context.getHand() == InteractionHand.MAIN_HAND ? Reflections.instance$EquipmentSlot$MAINHAND : Reflections.instance$EquipmentSlot$OFFHAND;
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
|
||||
@Override
|
||||
protected void removeComponent(ComponentItemWrapper item, Object type) {
|
||||
item.resetComponent(type);
|
||||
item.removeComponent(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -123,10 +123,10 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
MIXED_RECIPE_CONVERTORS.put(RecipeTypes.SMITHING_TRANSFORM, (BukkitRecipeConvertor<CustomSmithingTransformRecipe<ItemStack>>) (id, recipe) -> {
|
||||
try {
|
||||
Object nmsRecipe = createMinecraftSmithingTransformRecipe(recipe);
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
nmsRecipe = Reflections.constructor$RecipeHolder.newInstance(
|
||||
Reflections.method$CraftRecipe$toMinecraft.invoke(null, new NamespacedKey(id.namespace(), id.value())), nmsRecipe);
|
||||
} else if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
} else if (VersionHelper.isOrAbove1_20_2()) {
|
||||
nmsRecipe = Reflections.constructor$RecipeHolder.newInstance(KeyUtils.toResourceLocation(id), nmsRecipe);
|
||||
} else {
|
||||
return () -> {};
|
||||
@@ -255,7 +255,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
instance = this;
|
||||
this.plugin = plugin;
|
||||
this.recipeEventListener = new RecipeEventListener(plugin, this, plugin.itemManager());
|
||||
this.crafterEventListener = VersionHelper.isVersionNewerThan1_21() ? new CrafterEventListener(plugin, this, plugin.itemManager()) : null;
|
||||
this.crafterEventListener = VersionHelper.isOrAbove1_21() ? new CrafterEventListener(plugin, this, plugin.itemManager()) : null;
|
||||
try {
|
||||
nmsRecipeManager = Reflections.method$MinecraftServer$getRecipeManager.invoke(Reflections.method$MinecraftServer$getServer.invoke(null));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
@@ -286,7 +286,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
@Override
|
||||
public void load() {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
try {
|
||||
this.stolenFeatureFlagSet = Reflections.field$RecipeManager$featureflagset.get(nmsRecipeManager);
|
||||
Reflections.field$RecipeManager$featureflagset.set(nmsRecipeManager, null);
|
||||
@@ -301,7 +301,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
super.unload();
|
||||
try {
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
Reflections.method$RecipeManager$finalizeRecipeLoading.invoke(nmsRecipeManager);
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
@@ -349,7 +349,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
|
||||
private void unregisterNMSRecipe(NamespacedKey key) {
|
||||
try {
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
Object recipeMap = Reflections.field$RecipeManager$recipes.get(nmsRecipeManager);
|
||||
Reflections.method$RecipeMap$removeRecipe.invoke(recipeMap, Reflections.method$CraftRecipe$toMinecraft.invoke(null, key));
|
||||
} else {
|
||||
@@ -363,7 +363,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
@SuppressWarnings("unchecked")
|
||||
private void injectDataPackRecipes() {
|
||||
try {
|
||||
Object fileToIdConverter = Reflections.method$FileToIdConverter$json.invoke(null, VersionHelper.isVersionNewerThan1_21() ? "recipe" : "recipes");
|
||||
Object fileToIdConverter = Reflections.method$FileToIdConverter$json.invoke(null, VersionHelper.isOrAbove1_21() ? "recipe" : "recipes");
|
||||
Object minecraftServer = Reflections.method$MinecraftServer$getServer.invoke(null);
|
||||
Object packRepository = Reflections.method$MinecraftServer$getPackRepository.invoke(minecraftServer);
|
||||
List<Object> selected = (List<Object>) Reflections.field$PackRepository$selected.get(packRepository);
|
||||
@@ -446,13 +446,13 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
this.delayedTasksOnMainThread.clear();
|
||||
|
||||
// give flags back on 1.21.2+
|
||||
if (VersionHelper.isVersionNewerThan1_21_2() && this.stolenFeatureFlagSet != null) {
|
||||
if (VersionHelper.isOrAbove1_21_2() && this.stolenFeatureFlagSet != null) {
|
||||
Reflections.field$RecipeManager$featureflagset.set(nmsRecipeManager(), this.stolenFeatureFlagSet);
|
||||
this.stolenFeatureFlagSet = null;
|
||||
}
|
||||
|
||||
// refresh recipes
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
Reflections.method$RecipeManager$finalizeRecipeLoading.invoke(nmsRecipeManager());
|
||||
}
|
||||
|
||||
@@ -460,11 +460,11 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
Reflections.method$DedicatedPlayerList$reloadRecipes.invoke(Reflections.field$CraftServer$playerList.get(Bukkit.getServer()));
|
||||
|
||||
// now we need to remove the fake `exact`
|
||||
if (VersionHelper.isVersionNewerThan1_21_4()) {
|
||||
if (VersionHelper.isOrAbove1_21_4()) {
|
||||
for (Object ingredient : injectedIngredients) {
|
||||
Reflections.field$Ingredient$itemStacks1_21_4.set(ingredient, null);
|
||||
}
|
||||
} else if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
} else if (VersionHelper.isOrAbove1_21_2()) {
|
||||
for (Object ingredient : injectedIngredients) {
|
||||
Reflections.field$Ingredient$itemStacks1_21_2.set(ingredient, null);
|
||||
}
|
||||
@@ -711,11 +711,11 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
|
||||
Object shapedRecipe = getNMSRecipe(id);
|
||||
recipeToMcRecipeHolder.put(recipe, shapedRecipe);
|
||||
if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
shapedRecipe = Reflections.field$RecipeHolder$recipe.get(shapedRecipe);
|
||||
}
|
||||
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
Reflections.field$ShapedRecipe$placementInfo.set(shapedRecipe, null);
|
||||
}
|
||||
|
||||
@@ -732,11 +732,11 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
|
||||
Object shapelessRecipe = getNMSRecipe(id);
|
||||
recipeToMcRecipeHolder.put(recipe, shapelessRecipe);
|
||||
if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
shapelessRecipe = Reflections.field$RecipeHolder$recipe.get(shapelessRecipe);
|
||||
}
|
||||
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
Reflections.field$ShapelessRecipe$placementInfo.set(shapelessRecipe, null);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -752,12 +752,12 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
Ingredient<ItemStack> actualIngredient = recipe.ingredient();
|
||||
Object smeltingRecipe = getNMSRecipe(id);
|
||||
recipeToMcRecipeHolder.put(recipe, smeltingRecipe);
|
||||
if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
smeltingRecipe = Reflections.field$RecipeHolder$recipe.get(smeltingRecipe);
|
||||
}
|
||||
|
||||
Object ingredient;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
ingredient = Reflections.field$SingleItemRecipe$input.get(smeltingRecipe);
|
||||
} else {
|
||||
ingredient = Reflections.field$AbstractCookingRecipe$input.get(smeltingRecipe);
|
||||
@@ -771,7 +771,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
// 获取nms配方,请注意1.20.1获取配方本身,而1.20.2+获取的是配方的holder
|
||||
// recipe on 1.20.1 and holder on 1.20.2+
|
||||
private static Object getNMSRecipe(Key id) throws ReflectiveOperationException {
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
Object resourceKey = Reflections.method$CraftRecipe$toMinecraft.invoke(null, new NamespacedKey(id.namespace(), id.value()));
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optional = (Optional<Object>) Reflections.method$RecipeManager$byKey.invoke(nmsRecipeManager, resourceKey);
|
||||
@@ -800,9 +800,9 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
Object ingredient = fakeIngredients.get(i);
|
||||
Ingredient<ItemStack> actualIngredient = actualIngredients.get(i);
|
||||
List<Object> items = getIngredientLooks(actualIngredient.items());
|
||||
if (VersionHelper.isVersionNewerThan1_21_4()) {
|
||||
if (VersionHelper.isOrAbove1_21_4()) {
|
||||
Reflections.field$Ingredient$itemStacks1_21_4.set(ingredient, new HashSet<>(items));
|
||||
} else if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
} else if (VersionHelper.isOrAbove1_21_2()) {
|
||||
Reflections.field$Ingredient$itemStacks1_21_2.set(ingredient, items);
|
||||
} else {
|
||||
Object itemStackArray = Array.newInstance(Reflections.clazz$ItemStack, items.size());
|
||||
@@ -845,21 +845,21 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
|
||||
// create nms smithing recipe for different versions
|
||||
private static Object createMinecraftSmithingTransformRecipe(CustomSmithingTransformRecipe<ItemStack> recipe) throws ReflectiveOperationException {
|
||||
if (VersionHelper.isVersionNewerThan1_21_5()) {
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
return Reflections.constructor$SmithingTransformRecipe.newInstance(
|
||||
toOptionalMinecraftIngredient(recipe.template()),
|
||||
toMinecraftIngredient(recipe.base()),
|
||||
toOptionalMinecraftIngredient(recipe.addition()),
|
||||
toTransmuteResult(recipe.result(ItemBuildContext.EMPTY))
|
||||
);
|
||||
} else if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
} else if (VersionHelper.isOrAbove1_21_2()) {
|
||||
return Reflections.constructor$SmithingTransformRecipe.newInstance(
|
||||
toOptionalMinecraftIngredient(recipe.template()),
|
||||
toOptionalMinecraftIngredient(recipe.base()),
|
||||
toOptionalMinecraftIngredient(recipe.addition()),
|
||||
FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(recipe.result(ItemBuildContext.EMPTY))
|
||||
);
|
||||
} else if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
} else if (VersionHelper.isOrAbove1_20_2()) {
|
||||
return Reflections.constructor$SmithingTransformRecipe.newInstance(
|
||||
toMinecraftIngredient(recipe.template()),
|
||||
toMinecraftIngredient(recipe.base()),
|
||||
|
||||
@@ -279,7 +279,7 @@ public class RecipeEventListener implements Listener {
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBlockIgnite(BlockIgniteEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) return;
|
||||
if (VersionHelper.isOrAbove1_21_2()) return;
|
||||
Block block = event.getBlock();
|
||||
Material material = block.getType();
|
||||
if (material == Material.CAMPFIRE) {
|
||||
@@ -308,7 +308,7 @@ public class RecipeEventListener implements Listener {
|
||||
plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
}
|
||||
}
|
||||
} else if (!VersionHelper.isVersionNewerThan1_21_2() && material == Material.CAMPFIRE) {
|
||||
} else if (!VersionHelper.isOrAbove1_21_2() && material == Material.CAMPFIRE) {
|
||||
if (block.getState() instanceof Campfire campfire) {
|
||||
try {
|
||||
Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(campfire);
|
||||
@@ -324,13 +324,13 @@ public class RecipeEventListener implements Listener {
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPutItemOnCampfire(PlayerInteractEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (!VersionHelper.isVersionNewerThan1_21_2()) return;
|
||||
if (!VersionHelper.isOrAbove1_21_2()) return;
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||
Block clicked = event.getClickedBlock();
|
||||
if (clicked == null) return;
|
||||
Material type = clicked.getType();
|
||||
if (type != Material.CAMPFIRE && type != Material.SOUL_CAMPFIRE) return;
|
||||
if (!VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (!VersionHelper.isOrAbove1_21_2()) {
|
||||
if (clicked.getState() instanceof Campfire campfire) {
|
||||
try {
|
||||
Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(campfire);
|
||||
@@ -375,7 +375,7 @@ public class RecipeEventListener implements Listener {
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onCampfireCook(CampfireStartEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (!VersionHelper.isVersionNewerThan1_21_2()) return;
|
||||
if (!VersionHelper.isOrAbove1_21_2()) return;
|
||||
CampfireRecipe recipe = event.getRecipe();
|
||||
Key recipeId = new Key(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
|
||||
@@ -406,7 +406,7 @@ public class RecipeEventListener implements Listener {
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onCampfireCook(BlockCookEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (!VersionHelper.isVersionNewerThan1_21_2()) return;
|
||||
if (!VersionHelper.isOrAbove1_21_2()) return;
|
||||
Material type = event.getBlock().getType();
|
||||
if (type != Material.CAMPFIRE && type != Material.SOUL_CAMPFIRE) return;
|
||||
CampfireRecipe recipe = (CampfireRecipe) event.getRecipe();
|
||||
@@ -563,7 +563,7 @@ public class RecipeEventListener implements Listener {
|
||||
String renameText;
|
||||
int maxRepairCost;
|
||||
//int previousCost;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
AnvilView anvilView = event.getView();
|
||||
renameText = anvilView.getRenameText();
|
||||
maxRepairCost = anvilView.getMaximumRepairCost();
|
||||
@@ -588,10 +588,10 @@ public class RecipeEventListener implements Listener {
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to get hover name", e);
|
||||
}
|
||||
} else if (VersionHelper.isVersionNewerThan1_20_5() && wrappedFirst.hasComponent(ComponentTypes.CUSTOM_NAME)) {
|
||||
} else if (VersionHelper.isOrAbove1_20_5() && wrappedFirst.hasComponent(ComponentTypes.CUSTOM_NAME)) {
|
||||
repairCost += 1;
|
||||
wrappedFirst.customName(null);
|
||||
} else if (!VersionHelper.isVersionNewerThan1_20_5() && wrappedFirst.hasTag("display", "Name")) {
|
||||
} else if (!VersionHelper.isOrAbove1_20_5() && wrappedFirst.hasTag("display", "Name")) {
|
||||
repairCost += 1;
|
||||
wrappedFirst.customName(null);
|
||||
}
|
||||
@@ -601,7 +601,7 @@ public class RecipeEventListener implements Listener {
|
||||
// To fix some client side visual issues
|
||||
try {
|
||||
Object anvilMenu;
|
||||
if (VersionHelper.isVersionNewerThan1_21()) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
anvilMenu = Reflections.field$CraftInventoryView$container.get(event.getView());
|
||||
} else {
|
||||
anvilMenu = Reflections.field$CraftInventoryAnvil$menu.get(inventory);
|
||||
@@ -611,7 +611,7 @@ public class RecipeEventListener implements Listener {
|
||||
this.plugin.logger().warn("Failed to broadcast changes", e);
|
||||
}
|
||||
|
||||
if (VersionHelper.isVersionNewerThan1_21()) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
AnvilView anvilView = event.getView();
|
||||
anvilView.setRepairCost(finalCost);
|
||||
anvilView.setRepairItemCountCost(actualConsumedAmount);
|
||||
@@ -622,7 +622,7 @@ public class RecipeEventListener implements Listener {
|
||||
|
||||
Player player;
|
||||
try {
|
||||
player = (Player) Reflections.method$InventoryView$getPlayer.invoke(VersionHelper.isVersionNewerThan1_21() ? event.getView() : LegacyInventoryUtils.getView(event));
|
||||
player = (Player) Reflections.method$InventoryView$getPlayer.invoke(VersionHelper.isOrAbove1_21() ? event.getView() : LegacyInventoryUtils.getView(event));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to get inventory viewer", e);
|
||||
return;
|
||||
@@ -659,7 +659,7 @@ public class RecipeEventListener implements Listener {
|
||||
wrappedFirst.getCustomItem().ifPresent(item -> {
|
||||
if (!item.settings().renameable()) {
|
||||
String renameText;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
AnvilView anvilView = event.getView();
|
||||
renameText = anvilView.getRenameText();
|
||||
} else {
|
||||
|
||||
@@ -72,7 +72,7 @@ public class BukkitVanillaLootManager extends AbstractVanillaLootManager impleme
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
if (event.getDamageSource().getCausingEntity() instanceof Player player) {
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
builder.withParameter(LootParameters.PLAYER, serverPlayer);
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerResourcePackStatusEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -49,27 +48,17 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
if (Config.sendPackOnJoin() && !VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (Config.sendPackOnJoin() && !VersionHelper.isOrAbove1_20_2()) {
|
||||
Player player = plugin.adapt(event.getPlayer());
|
||||
this.sendResourcePack(player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onResourcePackStatus(PlayerResourcePackStatusEvent event) {
|
||||
// for 1.20.1 servers, not recommended to use
|
||||
if (Config.sendPackOnJoin() && Config.kickOnDeclined() && !VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (event.getStatus() == PlayerResourcePackStatusEvent.Status.DECLINED || event.getStatus() == PlayerResourcePackStatusEvent.Status.FAILED_DOWNLOAD) {
|
||||
event.getPlayer().kick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
if (ReloadCommand.RELOAD_PACK_FLAG || CraftEngine.instance().isInitializing()) {
|
||||
super.load();
|
||||
if (Config.sendPackOnJoin() && VersionHelper.isVersionNewerThan1_20_2() && !(resourcePackHost() instanceof NoneHost)) {
|
||||
if (Config.sendPackOnJoin() && VersionHelper.isOrAbove1_20_2() && !(resourcePackHost() instanceof NoneHost)) {
|
||||
this.modifyServerSettings();
|
||||
}
|
||||
}
|
||||
@@ -80,7 +69,7 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
Object settings = Reflections.field$DedicatedServer$settings.get(Reflections.method$MinecraftServer$getServer.invoke(null));
|
||||
Object properties = Reflections.field$DedicatedServerSettings$properties.get(settings);
|
||||
Object info;
|
||||
if (VersionHelper.isVersionNewerThan1_20_3()) {
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
info = Reflections.constructor$ServerResourcePackInfo.newInstance(new UUID(0, 0), FAKE_URL, "", Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
} else {
|
||||
info = Reflections.constructor$ServerResourcePackInfo.newInstance(FAKE_URL, "", Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
@@ -95,7 +84,7 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
public void unload() {
|
||||
super.unload();
|
||||
if (ReloadCommand.RELOAD_PACK_FLAG) {
|
||||
if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
this.resetServerSettings();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import net.momirealms.craftengine.bukkit.advancement.BukkitAdvancementManager;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CraftEngineReloadEvent;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.papi.PlaceholderAPIUtils;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.BukkitHitBoxTypes;
|
||||
import net.momirealms.craftengine.bukkit.font.BukkitFontManager;
|
||||
@@ -25,8 +24,8 @@ import net.momirealms.craftengine.bukkit.sound.BukkitSoundManager;
|
||||
import net.momirealms.craftengine.bukkit.util.EventUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.ItemManager;
|
||||
import net.momirealms.craftengine.core.plugin.CompatibilityManager;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.classpath.ReflectionClassPathAppender;
|
||||
import net.momirealms.craftengine.core.plugin.command.sender.SenderFactory;
|
||||
@@ -51,10 +50,12 @@ import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class BukkitCraftEngine extends CraftEngine {
|
||||
private static final String COMPATIBILITY_CLASS = "net.momirealms.craftengine.bukkit.compatibility.BukkitCompatibilityManager";
|
||||
private static BukkitCraftEngine instance;
|
||||
private final JavaPlugin bootstrap;
|
||||
private SchedulerTask tickTask;
|
||||
@@ -63,7 +64,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
private boolean requiresRestart = false;
|
||||
private boolean hasMod = false;
|
||||
private AntiGriefLib antiGrief;
|
||||
private boolean hasPlaceholderAPI;
|
||||
|
||||
public BukkitCraftEngine(JavaPlugin bootstrap) {
|
||||
super((p) -> {
|
||||
@@ -85,6 +85,12 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
Class<?> compatibilityClass = Objects.requireNonNull(ReflectionUtils.getClazz(COMPATIBILITY_CLASS), "Compatibility class not found");
|
||||
try {
|
||||
super.compatibilityManager = (CompatibilityManager) Objects.requireNonNull(ReflectionUtils.getConstructor(compatibilityClass, 0)).newInstance(this);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
logger().warn("Compatibility class could not be instantiated: " + compatibilityClass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,6 +102,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
super.blockManager = new BukkitBlockManager(this);
|
||||
super.furnitureManager = new BukkitFurnitureManager(this);
|
||||
this.successfullyLoaded = true;
|
||||
super.compatibilityManager().onLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,12 +166,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
super.fontManager = new BukkitFontManager(this);
|
||||
super.advancementManager = new BukkitAdvancementManager(this);
|
||||
super.onPluginEnable();
|
||||
// compatibility
|
||||
// register expansion
|
||||
if (this.isPluginEnabled("PlaceholderAPI")) {
|
||||
PlaceholderAPIUtils.registerExpansions(this);
|
||||
this.hasPlaceholderAPI = true;
|
||||
}
|
||||
super.compatibilityManager().onEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -204,6 +206,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
}
|
||||
}, 1, 1);
|
||||
}
|
||||
super.compatibilityManager().onDelayedEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -270,21 +273,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlaceholderAPI() {
|
||||
return this.hasPlaceholderAPI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginEnabled(String plugin) {
|
||||
return Bukkit.getPluginManager().isPluginEnabled(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parse(Player player, String text) {
|
||||
return PlaceholderAPIUtils.parse((org.bukkit.entity.Player) player.platformPlayer(), text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitNetworkManager networkManager() {
|
||||
return (BukkitNetworkManager) networkManager;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class BukkitGuiManager implements GuiManager, Listener {
|
||||
if (VersionHelper.isFolia()) {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
this.plugin.scheduler().sync().run(() -> {
|
||||
org.bukkit.inventory.Inventory top = !VersionHelper.isVersionNewerThan1_21() ? LegacyInventoryUtils.getTopInventory(player) : player.getOpenInventory().getTopInventory();
|
||||
org.bukkit.inventory.Inventory top = !VersionHelper.isOrAbove1_21() ? LegacyInventoryUtils.getTopInventory(player) : player.getOpenInventory().getTopInventory();
|
||||
if (top.getHolder() instanceof CraftEngineInventoryHolder holder) {
|
||||
holder.gui().onTimer();
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class BukkitGuiManager implements GuiManager, Listener {
|
||||
}
|
||||
} else {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
org.bukkit.inventory.Inventory top = !VersionHelper.isVersionNewerThan1_21() ? LegacyInventoryUtils.getTopInventory(player) : player.getOpenInventory().getTopInventory();
|
||||
org.bukkit.inventory.Inventory top = !VersionHelper.isOrAbove1_21() ? LegacyInventoryUtils.getTopInventory(player) : player.getOpenInventory().getTopInventory();
|
||||
if (top.getHolder() instanceof CraftEngineInventoryHolder holder) {
|
||||
holder.gui().onTimer();
|
||||
}
|
||||
|
||||
@@ -318,11 +318,11 @@ public class BukkitInjector {
|
||||
.intercept(FieldAccessor.ofField("lastCustomRecipe"))
|
||||
.method(ElementMatchers.named("getRecipeFor").or(ElementMatchers.named("a")))
|
||||
.intercept(MethodDelegation.to(
|
||||
VersionHelper.isVersionNewerThan1_21_2() ?
|
||||
VersionHelper.isOrAbove1_21_2() ?
|
||||
GetRecipeForMethodInterceptor1_21_2.INSTANCE :
|
||||
(VersionHelper.isVersionNewerThan1_21() ?
|
||||
(VersionHelper.isOrAbove1_21() ?
|
||||
GetRecipeForMethodInterceptor1_21.INSTANCE :
|
||||
VersionHelper.isVersionNewerThan1_20_5() ?
|
||||
VersionHelper.isOrAbove1_20_5() ?
|
||||
GetRecipeForMethodInterceptor1_20_5.INSTANCE :
|
||||
GetRecipeForMethodInterceptor1_20.INSTANCE)
|
||||
))
|
||||
@@ -346,7 +346,7 @@ public class BukkitInjector {
|
||||
InjectedCacheCheck injectedChecker = (InjectedCacheCheck) Reflections.UNSAFE.allocateInstance(clazz$InjectedCacheChecker);
|
||||
injectedChecker.recipeType(recipeType);
|
||||
Reflections.field$AbstractFurnaceBlockEntity$quickCheck.set(entity, injectedChecker);
|
||||
} else if (!VersionHelper.isVersionNewerThan1_21_2() && Reflections.clazz$CampfireBlockEntity.isInstance(entity)) {
|
||||
} else if (!VersionHelper.isOrAbove1_21_2() && Reflections.clazz$CampfireBlockEntity.isInstance(entity)) {
|
||||
Object quickCheck = Reflections.field$CampfireBlockEntity$quickCheck.get(entity);
|
||||
if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected
|
||||
InjectedCacheCheck injectedChecker = (InjectedCacheCheck) Reflections.UNSAFE.allocateInstance(clazz$InjectedCacheChecker);
|
||||
@@ -368,6 +368,22 @@ public class BukkitInjector {
|
||||
}
|
||||
}
|
||||
|
||||
// public synchronized static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEWorld ceWorld, SectionPos pos) {
|
||||
// try {
|
||||
// Object container = FastNMS.INSTANCE.field$LevelChunkSection$states(targetSection);
|
||||
// if (!(container instanceof InjectedPalettedContainerHolder)) {
|
||||
// InjectedPalettedContainerHolder injectedObject = FastNMS.INSTANCE.createInjectedPalettedContainerHolder(container);
|
||||
// injectedObject.ceSection(ceSection);
|
||||
// injectedObject.ceWorld(ceWorld);
|
||||
// injectedObject.cePos(pos);
|
||||
// Reflections.varHandle$PalettedContainer$data.setVolatile(injectedObject, Reflections.varHandle$PalettedContainer$data.get(container));
|
||||
// Reflections.field$LevelChunkSection$states.set(targetSection, injectedObject);
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// CraftEngine.instance().logger().severe("Failed to inject chunk section", e);
|
||||
// }
|
||||
// }
|
||||
|
||||
public static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEWorld ceWorld, SectionPos pos) {
|
||||
try {
|
||||
Object container = FastNMS.INSTANCE.field$LevelChunkSection$states(targetSection);
|
||||
@@ -385,7 +401,7 @@ public class BukkitInjector {
|
||||
}
|
||||
}
|
||||
|
||||
public static void uninjectLevelChunkSection(Object section) {
|
||||
public synchronized static void uninjectLevelChunkSection(Object section) {
|
||||
try {
|
||||
Object states = FastNMS.INSTANCE.field$LevelChunkSection$states(section);
|
||||
if (states instanceof InjectedPalettedContainerHolder holder) {
|
||||
@@ -750,7 +766,7 @@ public class BukkitInjector {
|
||||
Object direction;
|
||||
Object serverLevel;
|
||||
Object blockPos;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
direction = args[4];
|
||||
serverLevel = args[1];
|
||||
blockPos = args[3];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
@@ -16,10 +17,7 @@ import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetworkManager;
|
||||
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
|
||||
import net.momirealms.craftengine.core.util.ListMonitor;
|
||||
import net.momirealms.craftengine.core.util.TriConsumer;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -72,10 +70,12 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
private static final String PACKET_DECODER = "craftengine_decoder";
|
||||
|
||||
private static boolean hasModelEngine;
|
||||
private static boolean hasViaVersion;
|
||||
|
||||
public BukkitNetworkManager(BukkitCraftEngine plugin) {
|
||||
instance = this;
|
||||
hasModelEngine = Bukkit.getPluginManager().getPlugin("ModelEngine") != null;
|
||||
hasViaVersion = Bukkit.getPluginManager().getPlugin("ViaVersion") != null;
|
||||
this.plugin = plugin;
|
||||
// set up packet id
|
||||
this.packetIds = setupPacketIds();
|
||||
@@ -101,6 +101,8 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
// set up mod channel
|
||||
this.plugin.bootstrap().getServer().getMessenger().registerIncomingPluginChannel(this.plugin.bootstrap(), MOD_CHANNEL, this);
|
||||
this.plugin.bootstrap().getServer().getMessenger().registerOutgoingPluginChannel(this.plugin.bootstrap(), MOD_CHANNEL);
|
||||
// 配置via频道
|
||||
this.plugin.bootstrap().getServer().getMessenger().registerIncomingPluginChannel(this.plugin.bootstrap(), VIA_CHANNEL, this);
|
||||
// Inject server channel
|
||||
try {
|
||||
Object server = Reflections.method$MinecraftServer$getServer.invoke(null);
|
||||
@@ -119,7 +121,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
}
|
||||
|
||||
private PacketIds setupPacketIds() {
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
return new PacketIds1_20_5();
|
||||
} else {
|
||||
return new PacketIds1_20();
|
||||
@@ -127,7 +129,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
}
|
||||
|
||||
private void registerPacketHandlers() {
|
||||
registerNMSPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, Reflections.clazz$ClientboundLevelChunkWithLightPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.PLAYER_INFO_UPDATE, Reflections.clazz$ClientboundPlayerInfoUpdatePacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.PLAYER_ACTION, Reflections.clazz$ServerboundPlayerActionPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.SWING_HAND, Reflections.clazz$ServerboundSwingPacket);
|
||||
@@ -147,20 +148,24 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerNMSPacketConsumer(PacketConsumers.EDIT_BOOK, Reflections.clazz$ServerboundEditBookPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.CUSTOM_PAYLOAD, Reflections.clazz$ServerboundCustomPayloadPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_PUSH, Reflections.clazz$ClientboundResourcePackPushPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.HANDSHAKE_C2S, Reflections.clazz$ClientIntentionPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.LOGIN_ACKNOWLEDGED, Reflections.clazz$ServerboundLoginAcknowledgedPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, Reflections.clazz$ServerboundResourcePackPacket);
|
||||
registerByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_21_3() ? PacketConsumers.LEVEL_PARTICLE_1_21_3 : (VersionHelper.isVersionNewerThan1_20_5() ? PacketConsumers.LEVEL_PARTICLE_1_20_5 : PacketConsumers.LEVEL_PARTICLE_1_20), this.packetIds.clientboundLevelParticlesPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_21_3() ? PacketConsumers.LEVEL_PARTICLE_1_21_3 : (VersionHelper.isOrAbove1_20_5() ? PacketConsumers.LEVEL_PARTICLE_1_20_5 : PacketConsumers.LEVEL_PARTICLE_1_20), this.packetIds.clientboundLevelParticlesPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.LEVEL_EVENT, this.packetIds.clientboundLevelEventPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.OPEN_SCREEN_1_20_3 : PacketConsumers.OPEN_SCREEN_1_20, this.packetIds.clientboundOpenScreenPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.SET_TITLE_TEXT_1_20_3 : PacketConsumers.SET_TITLE_TEXT_1_20, this.packetIds.clientboundSetTitleTextPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.SET_SUBTITLE_TEXT_1_20_3 : PacketConsumers.SET_SUBTITLE_TEXT_1_20, this.packetIds.clientboundSetSubtitleTextPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.SET_ACTIONBAR_TEXT_1_20_3 : PacketConsumers.SET_ACTIONBAR_TEXT_1_20, this.packetIds.clientboundSetActionBarTextPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.BOSS_EVENT_1_20_3 : PacketConsumers.BOSS_EVENT_1_20, this.packetIds.clientboundBossEventPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.SYSTEM_CHAT_1_20_3 : PacketConsumers.SYSTEM_CHAT_1_20, this.packetIds.clientboundSystemChatPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.TAB_LIST_1_20_3 : PacketConsumers.TAB_LIST_1_20, this.packetIds.clientboundTabListPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.TEAM_1_20_3 : PacketConsumers.TEAM_1_20, this.packetIds.clientboundSetPlayerTeamPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.SET_OBJECTIVE_1_20_3 : PacketConsumers.SET_OBJECTIVE_1_20, this.packetIds.clientboundSetObjectivePacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SET_SCORE_1_20_3, VersionHelper.isVersionNewerThan1_20_3() ? this.packetIds.clientboundSetScorePacket() : -1);
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.OPEN_SCREEN_1_20_3 : PacketConsumers.OPEN_SCREEN_1_20, this.packetIds.clientboundOpenScreenPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.SET_TITLE_TEXT_1_20_3 : PacketConsumers.SET_TITLE_TEXT_1_20, this.packetIds.clientboundSetTitleTextPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.SET_SUBTITLE_TEXT_1_20_3 : PacketConsumers.SET_SUBTITLE_TEXT_1_20, this.packetIds.clientboundSetSubtitleTextPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.SET_ACTIONBAR_TEXT_1_20_3 : PacketConsumers.SET_ACTIONBAR_TEXT_1_20, this.packetIds.clientboundSetActionBarTextPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.BOSS_EVENT_1_20_3 : PacketConsumers.BOSS_EVENT_1_20, this.packetIds.clientboundBossEventPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.SYSTEM_CHAT_1_20_3 : PacketConsumers.SYSTEM_CHAT_1_20, this.packetIds.clientboundSystemChatPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.TAB_LIST_1_20_3 : PacketConsumers.TAB_LIST_1_20, this.packetIds.clientboundTabListPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.TEAM_1_20_3 : PacketConsumers.TEAM_1_20, this.packetIds.clientboundSetPlayerTeamPacket());
|
||||
registerByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.SET_OBJECTIVE_1_20_3 : PacketConsumers.SET_OBJECTIVE_1_20, this.packetIds.clientboundSetObjectivePacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SET_SCORE_1_20_3, VersionHelper.isOrAbove1_20_3() ? this.packetIds.clientboundSetScorePacket() : -1);
|
||||
registerByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.ADD_ENTITY_BYTEBUFFER, this.packetIds.clientboundAddEntityPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket());
|
||||
@@ -202,9 +207,17 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
return this.onlineUserArray;
|
||||
}
|
||||
|
||||
// 保留仅注册入频道用
|
||||
@Override
|
||||
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, byte @NotNull [] message) {}
|
||||
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, byte @NotNull [] message) {
|
||||
if (channel.equals(VIA_CHANNEL)) {
|
||||
BukkitServerPlayer user = plugin.adapt(player);
|
||||
if (user != null) {
|
||||
JsonObject payload = GsonHelper.get().fromJson(new String(message), JsonObject.class);
|
||||
int version = payload.get("version").getAsInt();
|
||||
user.setProtocolVersion(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
@@ -289,6 +302,10 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
return hasModelEngine;
|
||||
}
|
||||
|
||||
public static boolean hasViaVersion() {
|
||||
return hasViaVersion;
|
||||
}
|
||||
|
||||
public void simulatePacket(@NotNull NetWorkUser player, Object packet) {
|
||||
Channel channel = player.nettyChannel();
|
||||
if (channel.isOpen()) {
|
||||
|
||||
@@ -9,7 +9,6 @@ import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
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.compatibility.modelengine.ModelEngineUtils;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior;
|
||||
@@ -41,6 +40,7 @@ import net.momirealms.craftengine.core.world.EntityHitResult;
|
||||
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||
import net.momirealms.craftengine.core.world.chunk.Palette;
|
||||
import net.momirealms.craftengine.core.world.chunk.PalettedContainer;
|
||||
import net.momirealms.craftengine.core.world.chunk.packet.BlockEntityData;
|
||||
import net.momirealms.craftengine.core.world.chunk.packet.MCSection;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
@@ -63,7 +63,6 @@ public class PacketConsumers {
|
||||
private static int[] mappingsMOD;
|
||||
private static IntIdentityList BLOCK_LIST;
|
||||
private static IntIdentityList BIOME_LIST;
|
||||
private static final UUID EMPTY_UUID = new UUID(0, 0);
|
||||
|
||||
public static void init(Map<Integer, Integer> map, int registrySize) {
|
||||
mappings = new int[registrySize];
|
||||
@@ -94,15 +93,53 @@ public class PacketConsumers {
|
||||
return mappingsMOD[stateId];
|
||||
}
|
||||
|
||||
// TODO Use bytebuffer?
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> LEVEL_CHUNK_WITH_LIGHT = (user, event, packet) -> {
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> LEVEL_CHUNK_WITH_LIGHT = (user, event) -> {
|
||||
try {
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int chunkX = buf.readInt();
|
||||
int chunkZ = buf.readInt();
|
||||
boolean named = !VersionHelper.isOrAbove1_20_2();
|
||||
// ClientboundLevelChunkPacketData
|
||||
int heightmapsCount = 0;
|
||||
Map<Integer, long[]> heightmapsMap = null;
|
||||
Tag heightmaps = null;
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
heightmapsMap = new HashMap<>();
|
||||
heightmapsCount = buf.readVarInt();
|
||||
for (int i = 0; i < heightmapsCount; i++) {
|
||||
int key = buf.readVarInt();
|
||||
long[] value = buf.readLongArray();
|
||||
heightmapsMap.put(key, value);
|
||||
}
|
||||
} else {
|
||||
heightmaps = buf.readNbt(named);
|
||||
}
|
||||
|
||||
int varInt = buf.readVarInt();
|
||||
byte[] buffer = new byte[varInt];
|
||||
buf.readBytes(buffer);
|
||||
int blockEntitiesDataCount = buf.readVarInt();
|
||||
List<BlockEntityData> blockEntitiesData = new ArrayList<>();
|
||||
for (int i = 0; i < blockEntitiesDataCount; i++) {
|
||||
byte packedXZ = buf.readByte();
|
||||
short y = buf.readShort();
|
||||
int type = buf.readVarInt();
|
||||
Tag tag = buf.readNbt(named);
|
||||
BlockEntityData blockEntityData = new BlockEntityData(packedXZ, y, type, tag);
|
||||
blockEntitiesData.add(blockEntityData);
|
||||
}
|
||||
// ClientboundLightUpdatePacketData
|
||||
BitSet skyYMask = buf.readBitSet();
|
||||
BitSet blockYMask = buf.readBitSet();
|
||||
BitSet emptySkyYMask = buf.readBitSet();
|
||||
BitSet emptyBlockYMask = buf.readBitSet();
|
||||
List<byte[]> skyUpdates = buf.readByteArrayList(2048);
|
||||
List<byte[]> blockUpdates = buf.readByteArrayList(2048);
|
||||
// 开始处理
|
||||
if (user.clientModEnabled()) {
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
Object chunkData = FastNMS.INSTANCE.field$ClientboundLevelChunkWithLightPacket$chunkData(packet);
|
||||
byte[] buffer = (byte[]) Reflections.field$ClientboundLevelChunkPacketData$buffer.get(chunkData);
|
||||
ByteBuf buf = Unpooled.copiedBuffer(buffer);
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
ByteBuf byteBuf = Unpooled.copiedBuffer(buffer);
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf);
|
||||
FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
for (int i = 0, count = player.clientSideSectionCount(); i < count; i++) {
|
||||
try {
|
||||
@@ -126,13 +163,10 @@ public class PacketConsumers {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reflections.field$ClientboundLevelChunkPacketData$buffer.set(chunkData, newBuf.array());
|
||||
buffer = newBuf.array();
|
||||
} else {
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
Object chunkData = FastNMS.INSTANCE.field$ClientboundLevelChunkWithLightPacket$chunkData(packet);
|
||||
byte[] buffer = (byte[]) Reflections.field$ClientboundLevelChunkPacketData$buffer.get(chunkData);
|
||||
ByteBuf buf = Unpooled.copiedBuffer(buffer);
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
ByteBuf byteBuf = Unpooled.copiedBuffer(buffer);
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf);
|
||||
FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
for (int i = 0, count = player.clientSideSectionCount(); i < count; i++) {
|
||||
try {
|
||||
@@ -156,8 +190,38 @@ public class PacketConsumers {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reflections.field$ClientboundLevelChunkPacketData$buffer.set(chunkData, newBuf.array());
|
||||
buffer = newBuf.array();
|
||||
}
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeInt(chunkX);
|
||||
buf.writeInt(chunkZ);
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
buf.writeVarInt(heightmapsCount);
|
||||
assert heightmapsMap != null;
|
||||
for (Map.Entry<Integer, long[]> entry : heightmapsMap.entrySet()) {
|
||||
buf.writeVarInt(entry.getKey());
|
||||
buf.writeLongArray(entry.getValue());
|
||||
}
|
||||
} else {
|
||||
buf.writeNbt(heightmaps, named);
|
||||
}
|
||||
buf.writeVarInt(buffer.length);
|
||||
buf.writeBytes(buffer);
|
||||
buf.writeVarInt(blockEntitiesDataCount);
|
||||
for (BlockEntityData blockEntityData : blockEntitiesData) {
|
||||
buf.writeByte(blockEntityData.packedXZ());
|
||||
buf.writeShort(blockEntityData.y());
|
||||
buf.writeVarInt(blockEntityData.type());
|
||||
buf.writeNbt(blockEntityData.tag(), named);
|
||||
}
|
||||
buf.writeBitSet(skyYMask);
|
||||
buf.writeBitSet(blockYMask);
|
||||
buf.writeBitSet(emptySkyYMask);
|
||||
buf.writeBitSet(emptyBlockYMask);
|
||||
buf.writeByteArrayList(skyUpdates);
|
||||
buf.writeByteArrayList(blockUpdates);
|
||||
event.setChanged(true);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundLevelChunkWithLightPacket", e);
|
||||
}
|
||||
@@ -1174,7 +1238,7 @@ public class PacketConsumers {
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
String name = (String) Reflections.field$ServerboundHelloPacket$name.get(packet);
|
||||
player.setName(name);
|
||||
if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
UUID uuid = (UUID) Reflections.field$ServerboundHelloPacket$uuid.get(packet);
|
||||
player.setUUID(uuid);
|
||||
} else {
|
||||
@@ -1222,7 +1286,7 @@ public class PacketConsumers {
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
player.clearView();
|
||||
Object dimensionKey;
|
||||
if (!VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (!VersionHelper.isOrAbove1_20_2()) {
|
||||
dimensionKey = Reflections.field$ClientboundRespawnPacket$dimension.get(packet);
|
||||
} else {
|
||||
Object commonInfo = Reflections.field$ClientboundRespawnPacket$commonPlayerSpawnInfo.get(packet);
|
||||
@@ -1247,7 +1311,10 @@ public class PacketConsumers {
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
player.setConnectionState(ConnectionState.PLAY);
|
||||
Object dimensionKey;
|
||||
if (!VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (!VersionHelper.isOrAbove1_20_2()) {
|
||||
if (BukkitNetworkManager.hasViaVersion()) {
|
||||
user.setProtocolVersion(CraftEngine.instance().compatibilityManager().getPlayerProtocolVersion(player.uuid()));
|
||||
}
|
||||
dimensionKey = Reflections.field$ClientboundLoginPacket$dimension.get(packet);
|
||||
} else {
|
||||
Object commonInfo = Reflections.field$ClientboundLoginPacket$commonPlayerSpawnInfo.get(packet);
|
||||
@@ -1272,7 +1339,7 @@ public class PacketConsumers {
|
||||
// When the hotbar is full, the latest creative mode inventory can only be accessed when the player opens the inventory screen. Currently, it is not worth further handling this issue.
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> SET_CREATIVE_SLOT = (user, event, packet) -> {
|
||||
try {
|
||||
if (VersionHelper.isVersionNewerThan1_21_4()) return;
|
||||
if (VersionHelper.isOrAbove1_21_4()) return;
|
||||
if (!user.isOnline()) return;
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
if (VersionHelper.isFolia()) {
|
||||
@@ -1295,7 +1362,7 @@ public class PacketConsumers {
|
||||
Player bukkitPlayer = player.platformPlayer();
|
||||
if (bukkitPlayer == null) return;
|
||||
if (bukkitPlayer.getGameMode() != GameMode.CREATIVE) return;
|
||||
int slot = VersionHelper.isVersionNewerThan1_20_5() ? Reflections.field$ServerboundSetCreativeModeSlotPacket$slotNum.getShort(packet) : Reflections.field$ServerboundSetCreativeModeSlotPacket$slotNum.getInt(packet);
|
||||
int slot = VersionHelper.isOrAbove1_20_5() ? Reflections.field$ServerboundSetCreativeModeSlotPacket$slotNum.getShort(packet) : Reflections.field$ServerboundSetCreativeModeSlotPacket$slotNum.getInt(packet);
|
||||
if (slot < 36 || slot > 44) return;
|
||||
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(Reflections.field$ServerboundSetCreativeModeSlotPacket$itemStack.get(packet));
|
||||
if (ItemUtils.isEmpty(item)) return;
|
||||
@@ -1585,7 +1652,7 @@ public class PacketConsumers {
|
||||
int entityId;
|
||||
if (BukkitNetworkManager.hasModelEngine()) {
|
||||
int fakeId = FastNMS.INSTANCE.field$ServerboundInteractPacket$entityId(packet);
|
||||
entityId = ModelEngineUtils.interactionToBaseEntity(fakeId);
|
||||
entityId = CraftEngine.instance().compatibilityManager().interactionToBaseEntity(fakeId);
|
||||
} else {
|
||||
entityId = FastNMS.INSTANCE.field$ServerboundInteractPacket$entityId(packet);
|
||||
}
|
||||
@@ -1867,7 +1934,7 @@ public class PacketConsumers {
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> CUSTOM_PAYLOAD = (user, event, packet) -> {
|
||||
try {
|
||||
if (!VersionHelper.isVersionNewerThan1_20_5()) return;
|
||||
if (!VersionHelper.isOrAbove1_20_5()) return;
|
||||
Object payload = Reflections.field$ServerboundCustomPayloadPacket$payload.get(packet);
|
||||
if (payload.getClass().equals(Reflections.clazz$DiscardedPayload)) {
|
||||
Object type = Reflections.method$CustomPacketPayload$type.invoke(payload);
|
||||
@@ -2149,7 +2216,7 @@ public class PacketConsumers {
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RESOURCE_PACK_PUSH = (user, event, packet) -> {
|
||||
try {
|
||||
if (!VersionHelper.isVersionNewerThan1_20_2()) return;
|
||||
if (!VersionHelper.isOrAbove1_20_2()) return;
|
||||
// we should only handle fake urls
|
||||
String url = FastNMS.INSTANCE.field$ClientboundResourcePackPushPacket$url(packet);
|
||||
if (!url.equals(BukkitPackManager.FAKE_URL)) {
|
||||
@@ -2178,4 +2245,45 @@ public class PacketConsumers {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundResourcePackPushPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HANDSHAKE_C2S = (user, event, packet) -> {
|
||||
try {
|
||||
if (BukkitNetworkManager.hasViaVersion()) return;
|
||||
int protocolVersion = Reflections.field$ClientIntentionPacket$protocolVersion.getInt(packet);
|
||||
user.setProtocolVersion(protocolVersion);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientIntentionPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> LOGIN_ACKNOWLEDGED = (user, event, packet) -> {
|
||||
try {
|
||||
if (BukkitNetworkManager.hasViaVersion()) {
|
||||
user.setProtocolVersion(CraftEngine.instance().compatibilityManager().getPlayerProtocolVersion(user.uuid()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundLoginAcknowledgedPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RESOURCE_PACK_RESPONSE = (user, event, packet) -> {
|
||||
try {
|
||||
if (user.sentResourcePack() || !Config.sendPackOnJoin() || !Config.kickOnDeclined()) return;
|
||||
Object action = Reflections.field$ServerboundResourcePackPacket$action.get(packet);
|
||||
if (action == null) return;
|
||||
if (action == Reflections.instance$ServerboundResourcePackPacket$Action$DECLINED
|
||||
|| action == Reflections.instance$ServerboundResourcePackPacket$Action$FAILED_DOWNLOAD) {
|
||||
Object kickPacket = Reflections.constructor$ClientboundDisconnectPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("multiplayer.requiredTexturePrompt.disconnect")));
|
||||
user.nettyChannel().writeAndFlush(kickPacket);
|
||||
user.nettyChannel().disconnect();
|
||||
return;
|
||||
}
|
||||
if (action == Reflections.instance$ServerboundResourcePackPacket$Action$SUCCESSFULLY_LOADED) {
|
||||
user.setSentResourcePack(true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundResourcePackPacket", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class PacketIdFinder {
|
||||
|
||||
static {
|
||||
try {
|
||||
if (VersionHelper.isVersionNewerThan1_21()) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
Object packetReport = Reflections.constructor$PacketReport.newInstance((Object) null);
|
||||
JsonElement jsonElement = (JsonElement) Reflections.method$PacketReport$serializePackets.invoke(packetReport);
|
||||
var play = jsonElement.getAsJsonObject().get("play");
|
||||
@@ -26,7 +26,7 @@ public class PacketIdFinder {
|
||||
ids.put(entry2.getKey(), entry2.getValue().getAsJsonObject().get("protocol_id").getAsInt());
|
||||
}
|
||||
}
|
||||
} else if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
} else if (VersionHelper.isOrAbove1_20_5()) {
|
||||
gamePacketIdsByName.putAll(FastNMS.INSTANCE.method$getGamePacketIdsByName());
|
||||
} else {
|
||||
gamePacketIdsByClazz.putAll(FastNMS.INSTANCE.method$getGamePacketIdsByClazz());
|
||||
|
||||
@@ -18,6 +18,7 @@ import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
import net.momirealms.craftengine.core.plugin.network.ProtocolVersion;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
@@ -39,6 +40,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class BukkitServerPlayer extends Player {
|
||||
private final BukkitCraftEngine plugin;
|
||||
// handshake
|
||||
private ProtocolVersion protocolVersion = ProtocolVersion.UNKNOWN;
|
||||
// connection state
|
||||
private final Channel channel;
|
||||
private String name;
|
||||
@@ -46,6 +49,7 @@ public class BukkitServerPlayer extends Player {
|
||||
private ConnectionState decoderState;
|
||||
private ConnectionState encoderState;
|
||||
private final Set<UUID> resourcePackUUID = Collections.synchronizedSet(new HashSet<>());
|
||||
private boolean sentResourcePack = !Config.sendPackOnJoin();
|
||||
// some references
|
||||
private Reference<org.bukkit.entity.Player> playerRef;
|
||||
private Reference<Object> serverPlayerRef;
|
||||
@@ -411,7 +415,7 @@ public class BukkitServerPlayer extends Player {
|
||||
}
|
||||
this.clientSideCanBreak = canBreak;
|
||||
if (canBreak) {
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
Object serverPlayer = serverPlayer();
|
||||
Object attributeInstance = Reflections.method$ServerPlayer$getAttribute.invoke(serverPlayer, Reflections.instance$Holder$Attribute$block_break_speed);
|
||||
Object newPacket = Reflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityID(), Lists.newArrayList(attributeInstance));
|
||||
@@ -421,8 +425,8 @@ public class BukkitServerPlayer extends Player {
|
||||
resetEffect(Reflections.instance$MobEffecr$haste);
|
||||
}
|
||||
} else {
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
Object attributeModifier = VersionHelper.isVersionNewerThan1_21() ?
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
Object attributeModifier = VersionHelper.isOrAbove1_21() ?
|
||||
Reflections.constructor$AttributeModifier.newInstance(KeyUtils.toResourceLocation("craftengine", "custom_hardness"), -9999d, Reflections.instance$AttributeModifier$Operation$ADD_VALUE) :
|
||||
Reflections.constructor$AttributeModifier.newInstance(UUID.randomUUID(), "craftengine:custom_hardness", -9999d, Reflections.instance$AttributeModifier$Operation$ADD_VALUE);
|
||||
Object attributeSnapshot = Reflections.constructor$ClientboundUpdateAttributesPacket$AttributeSnapshot.newInstance(Reflections.instance$Holder$Attribute$block_break_speed, 1d, Lists.newArrayList(attributeModifier));
|
||||
@@ -516,7 +520,7 @@ public class BukkitServerPlayer extends Player {
|
||||
// creative mode + invalid item in hand
|
||||
if (canInstabuild() && (itemMaterial == Material.DEBUG_STICK
|
||||
|| itemMaterial == Material.TRIDENT
|
||||
|| (VersionHelper.isVersionNewerThan1_20_5() && itemMaterial == MaterialUtils.MACE)
|
||||
|| (VersionHelper.isOrAbove1_20_5() && itemMaterial == MaterialUtils.MACE)
|
||||
|| item.is(ItemTags.SWORDS))) {
|
||||
return;
|
||||
}
|
||||
@@ -753,11 +757,31 @@ public class BukkitServerPlayer extends Player {
|
||||
|
||||
@Override
|
||||
public void addResourcePackUUID(UUID uuid) {
|
||||
if (VersionHelper.isVersionNewerThan1_20_3()) {
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
this.resourcePackUUID.add(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtocolVersion protocolVersion() {
|
||||
return this.protocolVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProtocolVersion(int protocolVersion) {
|
||||
this.protocolVersion = ProtocolVersion.getById(protocolVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sentResourcePack() {
|
||||
return this.sentResourcePack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSentResourcePack(boolean sentResourcePack) {
|
||||
this.sentResourcePack = sentResourcePack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearView() {
|
||||
this.entityTypeView.clear();
|
||||
@@ -766,7 +790,7 @@ public class BukkitServerPlayer extends Player {
|
||||
|
||||
@Override
|
||||
public void unloadCurrentResourcePack() {
|
||||
if (!VersionHelper.isVersionNewerThan1_20_3()) {
|
||||
if (!VersionHelper.isOrAbove1_20_3()) {
|
||||
return;
|
||||
}
|
||||
if (decoderState() == ConnectionState.PLAY && !this.resourcePackUUID.isEmpty()) {
|
||||
|
||||
@@ -33,7 +33,7 @@ public class BukkitSoundManager extends AbstractSoundManager {
|
||||
Object soundId = KeyUtils.toResourceLocation(jukeboxSong.sound());
|
||||
Object song = Reflections.method$Registry$get.invoke(Reflections.instance$InternalRegistries$JUKEBOX_SONG, resourceLocation);
|
||||
|
||||
Object soundEvent = VersionHelper.isVersionNewerThan1_21_2() ?
|
||||
Object soundEvent = VersionHelper.isOrAbove1_21_2() ?
|
||||
Reflections.constructor$SoundEvent.newInstance(soundId, Optional.of(jukeboxSong.range())) :
|
||||
Reflections.constructor$SoundEvent.newInstance(soundId, jukeboxSong.range(), false);
|
||||
Object soundHolder = Reflections.method$Holder$direct.invoke(null, soundEvent);
|
||||
|
||||
@@ -2,10 +2,8 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.core.block.BlockStateParser;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.PushReaction;
|
||||
import net.momirealms.craftengine.core.block.*;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Instrument;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MapColor;
|
||||
@@ -14,6 +12,9 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
@@ -32,6 +33,18 @@ public class BlockStateUtils {
|
||||
hasInit = true;
|
||||
}
|
||||
|
||||
public static boolean isCorrectTool(@NotNull ImmutableBlockState state, @Nullable Item<ItemStack> itemInHand) {
|
||||
BlockSettings settings = state.settings();
|
||||
if (settings.requireCorrectTool()) {
|
||||
if (itemInHand == null) return false;
|
||||
if (!settings.isCorrectTool(itemInHand.id()) &&
|
||||
(!settings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(itemInHand.getLiteralObject(), state.customBlockState().handle()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static List<Object> getAllBlockStates(String blockState) {
|
||||
int index = blockState.indexOf('[');
|
||||
if (index == -1) {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class BukkitReflectionUtils {
|
||||
private static final String PREFIX_MC = "net.minecraft.";
|
||||
@@ -66,4 +69,42 @@ public final class BukkitReflectionUtils {
|
||||
public static String assembleMCClass(String className) {
|
||||
return PREFIX_MC + className;
|
||||
}
|
||||
|
||||
public static Class<?> findReobfOrMojmapClass(String reobf, String mojmap) {
|
||||
return findReobfOrMojmapClass(reobf, mojmap, BukkitReflectionUtils::assembleMCClass);
|
||||
}
|
||||
|
||||
public static Class<?> findReobfOrMojmapClass(String reobf, String mojmap, Function<String, String> classDecorator) {
|
||||
if (VersionHelper.isMojmap()) return ReflectionUtils.getClazz(classDecorator.apply(mojmap));
|
||||
else return ReflectionUtils.getClazz(classDecorator.apply(reobf));
|
||||
}
|
||||
|
||||
public static Class<?> findReobfOrMojmapClass(List<String> reobf, String mojmap) {
|
||||
return findReobfOrMojmapClass(reobf, mojmap, BukkitReflectionUtils::assembleMCClass);
|
||||
}
|
||||
|
||||
public static Class<?> findReobfOrMojmapClass(List<String> reobf, String mojmap, Function<String, String> classDecorator) {
|
||||
if (VersionHelper.isMojmap()) return ReflectionUtils.getClazz(classDecorator.apply(mojmap));
|
||||
else return ReflectionUtils.getClazz(reobf.stream().map(classDecorator).toList().toArray(new String[0]));
|
||||
}
|
||||
|
||||
public static Class<?> findReobfOrMojmapClass(String reobf, List<String> mojmap) {
|
||||
return findReobfOrMojmapClass(reobf, mojmap, BukkitReflectionUtils::assembleMCClass);
|
||||
}
|
||||
|
||||
public static Class<?> findReobfOrMojmapClass(String reobf, List<String> mojmap, Function<String, String> classDecorator) {
|
||||
if (VersionHelper.isMojmap()) return ReflectionUtils.getClazz(mojmap.stream().map(classDecorator).toList().toArray(new String[0]));
|
||||
else return ReflectionUtils.getClazz(classDecorator.apply(reobf));
|
||||
}
|
||||
|
||||
public static Class<?> findReobfOrMojmapClass(List<String> reobf, List<String> mojmap) {
|
||||
return findReobfOrMojmapClass(reobf, mojmap, BukkitReflectionUtils::assembleMCClass);
|
||||
}
|
||||
|
||||
public static Class<?> findReobfOrMojmapClass(List<String> reobf, List<String> mojmap, Function<String, String> classDecorator) {
|
||||
String[] classes = VersionHelper.isMojmap()
|
||||
? mojmap.stream().map(classDecorator).toList().toArray(new String[0])
|
||||
: reobf.stream().map(classDecorator).toList().toArray(new String[0]);
|
||||
return ReflectionUtils.getClazz(classes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ 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.isVersionNewerThan1_20_2() ? 23 : 22;
|
||||
public static final int TEXT_DATA_ID = VersionHelper.isVersionNewerThan1_20_2() ? 23 : 22;
|
||||
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 CUSTOM_NAME_DATA_ID = 2;
|
||||
|
||||
public static byte encodeTextDisplayMask(boolean hasShadow, boolean isSeeThrough, boolean useDefaultBackground, int alignment) {
|
||||
|
||||
@@ -27,7 +27,7 @@ public class EntityUtils {
|
||||
}
|
||||
|
||||
public static Entity spawnEntity(World world, Location loc, EntityType type, Consumer<Entity> function) {
|
||||
if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
return world.spawnEntity(loc, type, CreatureSpawnEvent.SpawnReason.CUSTOM, function);
|
||||
} else {
|
||||
return LegacyEntityUtils.spawnEntity(world, loc, type, function);
|
||||
|
||||
@@ -15,9 +15,9 @@ public class RecipeUtils {
|
||||
public static List<Object> getIngredientsFromShapedRecipe(Object recipe) {
|
||||
List<Object> ingredients = new ArrayList<>();
|
||||
try {
|
||||
if (VersionHelper.isVersionNewerThan1_20_3()) {
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
Object pattern = Reflections.field$1_20_3$ShapedRecipe$pattern.get(recipe);
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
List<Optional<Object>> optionals = (List<Optional<Object>>) Reflections.field$ShapedRecipePattern$ingredients1_21_2.get(pattern);
|
||||
for (Optional<Object> optional : optionals) {
|
||||
optional.ifPresent(ingredients::add);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -74,7 +74,7 @@ public class BukkitWorld implements World {
|
||||
public void dropItemNaturally(Vec3d location, Item<?> item) {
|
||||
ItemStack itemStack = (ItemStack) item.load();
|
||||
if (ItemUtils.isEmpty(itemStack)) return;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
platformWorld().dropItemNaturally(new Location(null, location.x(), location.y(), location.z()), (ItemStack) item.getItem());
|
||||
} else {
|
||||
platformWorld().dropItemNaturally(new Location(null, location.x() - 0.5, location.y() - 0.5, location.z() - 0.5), (ItemStack) item.getItem());
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.world;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.compatibility.slimeworld.SlimeFormatStorageAdaptor;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
|
||||
@@ -10,18 +9,15 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||
import net.momirealms.craftengine.core.world.SectionPos;
|
||||
import net.momirealms.craftengine.core.world.WorldManager;
|
||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||
import net.momirealms.craftengine.core.world.chunk.CESection;
|
||||
import net.momirealms.craftengine.core.world.chunk.serialization.ChunkSerializer;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.DefaultStorageAdaptor;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.StorageAdaptor;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
@@ -29,10 +25,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.bukkit.event.world.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -57,16 +50,6 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
instance = this;
|
||||
this.plugin = plugin;
|
||||
this.worlds = new HashMap<>();
|
||||
if (VersionHelper.isVersionNewerThan1_21_4()) {
|
||||
try {
|
||||
Class.forName("com.infernalsuite.asp.api.AdvancedSlimePaperAPI");
|
||||
SlimeFormatStorageAdaptor adaptor = new SlimeFormatStorageAdaptor(this);
|
||||
this.storageAdaptor = adaptor;
|
||||
Bukkit.getPluginManager().registerEvents(adaptor, plugin.bootstrap());
|
||||
return;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
this.storageAdaptor = new DefaultStorageAdaptor();
|
||||
}
|
||||
|
||||
@@ -148,6 +131,11 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
for (Chunk chunk : world.getLoadedChunks()) {
|
||||
handleChunkUnload(ceWorld, chunk);
|
||||
}
|
||||
try {
|
||||
ceWorld.worldDataStorage().close();
|
||||
} catch (IOException e) {
|
||||
this.plugin.logger().warn("Error unloading world: " + world.getName(), e);
|
||||
}
|
||||
}
|
||||
this.worlds.clear();
|
||||
}
|
||||
@@ -198,6 +186,13 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
unloadWorld(new BukkitWorld(event.getWorld()));
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onWorldSave(WorldSaveEvent event) {
|
||||
for (CEWorld world : this.worldArray) {
|
||||
world.save();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadWorld(net.momirealms.craftengine.core.world.World world) {
|
||||
CEWorld ceWorld;
|
||||
@@ -270,10 +265,9 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
CEChunk ceChunk = world.getChunkAtIfLoaded(chunk.getX(), chunk.getZ());
|
||||
if (ceChunk != null) {
|
||||
try {
|
||||
world.worldDataStorage().writeChunkTagAt(pos, ChunkSerializer.serialize(ceChunk));
|
||||
world.worldDataStorage().writeChunkAt(pos, ceChunk, false);
|
||||
} catch (IOException e) {
|
||||
plugin.logger().warn("Failed to write chunk tag at " + chunk.getX() + " " + chunk.getZ(), e);
|
||||
return;
|
||||
this.plugin.logger().warn("Failed to write chunk tag at " + chunk.getX() + " " + chunk.getZ(), e);
|
||||
} finally {
|
||||
if (Config.restoreVanillaBlocks()) {
|
||||
CESection[] ceSections = ceChunk.sections();
|
||||
@@ -308,12 +302,7 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
if (ceWorld.isChunkLoaded(pos.longKey)) return;
|
||||
CEChunk ceChunk;
|
||||
try {
|
||||
CompoundTag chunkNbt = ceWorld.worldDataStorage().readChunkTagAt(pos);
|
||||
if (chunkNbt != null) {
|
||||
ceChunk = ChunkSerializer.deserialize(ceWorld, pos, chunkNbt);
|
||||
} else {
|
||||
ceChunk = new CEChunk(ceWorld, pos);
|
||||
}
|
||||
ceChunk = ceWorld.worldDataStorage().readChunkAt(ceWorld, pos);
|
||||
try {
|
||||
CESection[] ceSections = ceChunk.sections();
|
||||
Object worldServer = FastNMS.INSTANCE.field$CraftChunk$worldServer(chunk);
|
||||
|
||||
@@ -12,7 +12,7 @@ public class BlockNbtParser {
|
||||
|
||||
@Nullable
|
||||
public static CompoundTag deserialize(@NotNull CustomBlock block, @NotNull String data) {
|
||||
StringReader reader = new StringReader(data);
|
||||
StringReader reader = StringReader.simple(data);
|
||||
CompoundTag properties = new CompoundTag();
|
||||
while (reader.canRead()) {
|
||||
String propertyName = reader.readUnquotedString();
|
||||
|
||||
@@ -48,16 +48,11 @@ public class BlockStateHolder {
|
||||
return propertyMap.entrySet().stream()
|
||||
.map(entry -> {
|
||||
Property<?> property = entry.getKey();
|
||||
return property.name() + "=" + formatValue(property, entry.getValue());
|
||||
return property.name() + "=" + Property.formatValue(property, entry.getValue());
|
||||
})
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T extends Comparable<T>> String formatValue(Property<T> property, Comparable<?> value) {
|
||||
return property.valueName((T) value);
|
||||
}
|
||||
|
||||
public Collection<Property<?>> getProperties() {
|
||||
return Collections.unmodifiableSet(propertyMap.keySet());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
import net.momirealms.craftengine.core.util.StringReader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BlockStateMatcher {
|
||||
private final List<Pair<Property<?>, Comparable<?>>> properties;
|
||||
private final Key id;
|
||||
|
||||
public BlockStateMatcher(Key id, List<Pair<Property<?>, Comparable<?>>> properties) {
|
||||
this.properties = properties;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean matches(ImmutableBlockState state) {
|
||||
if (!state.owner().value().id.equals(this.id)) {
|
||||
return false;
|
||||
}
|
||||
for (Pair<Property<?>, Comparable<?>> pair : this.properties) {
|
||||
if (!state.get(pair.left()).equals(pair.right())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (properties.isEmpty()) {
|
||||
return id.toString();
|
||||
}
|
||||
return id + "[" + getPropertiesAsString() + "]";
|
||||
}
|
||||
|
||||
public String getPropertiesAsString() {
|
||||
return properties.stream()
|
||||
.map(entry -> {
|
||||
Property<?> property = entry.left();
|
||||
return property.name() + "=" + Property.formatValue(property, entry.right());
|
||||
})
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
@Nullable
|
||||
public static BlockStateMatcher deserialize(@NotNull String data) {
|
||||
StringReader reader = StringReader.simple(data);
|
||||
String blockIdString = reader.readUnquotedString();
|
||||
if (reader.canRead() && reader.peek() == ':') {
|
||||
reader.skip();
|
||||
blockIdString = blockIdString + ":" + reader.readUnquotedString();
|
||||
}
|
||||
Optional<Holder.Reference<CustomBlock>> optional = BuiltInRegistries.BLOCK.get(Key.from(blockIdString));
|
||||
if (optional.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Holder<CustomBlock> holder = optional.get();
|
||||
List<Pair<Property<?>, Comparable<?>>> properties = new ArrayList<>();
|
||||
if (reader.canRead() && reader.peek() == '[') {
|
||||
reader.skip();
|
||||
while (reader.canRead()) {
|
||||
reader.skipWhitespace();
|
||||
if (reader.peek() == ']') break;
|
||||
String propertyName = reader.readUnquotedString();
|
||||
reader.skipWhitespace();
|
||||
if (!reader.canRead() || reader.peek() != '=') {
|
||||
return null;
|
||||
}
|
||||
reader.skip();
|
||||
reader.skipWhitespace();
|
||||
String propertyValue = reader.readUnquotedString();
|
||||
Property<?> property = holder.value().getProperty(propertyName);
|
||||
if (property != null) {
|
||||
Optional<?> optionalValue = property.optional(propertyValue);
|
||||
if (optionalValue.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
properties.add(Pair.of(property, (Comparable<?>) optionalValue.get()));
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
reader.skipWhitespace();
|
||||
if (reader.canRead() && reader.peek() == ',') {
|
||||
reader.skip();
|
||||
}
|
||||
}
|
||||
reader.skipWhitespace();
|
||||
if (reader.canRead() && reader.peek() == ']') {
|
||||
reader.skip();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new BlockStateMatcher(holder.value().id(), properties);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ public class BlockStateParser {
|
||||
private Property<?> property;
|
||||
|
||||
public BlockStateParser(String data, int cursor) {
|
||||
this.reader = new StringReader(data.toLowerCase());
|
||||
this.reader = StringReader.simple(data.toLowerCase());
|
||||
this.reader.setCursor(cursor);
|
||||
this.cursor = cursor;
|
||||
this.replaceCursor = cursor;
|
||||
@@ -188,7 +188,7 @@ public class BlockStateParser {
|
||||
|
||||
@Nullable
|
||||
public static ImmutableBlockState deserialize(@NotNull String data) {
|
||||
StringReader reader = new StringReader(data);
|
||||
StringReader reader = StringReader.simple(data);
|
||||
String blockIdString = reader.readUnquotedString();
|
||||
if (reader.canRead() && reader.peek() == ':') {
|
||||
reader.skip();
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
import net.momirealms.craftengine.core.util.StringReader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class UnsafeBlockStateMatcher {
|
||||
private final List<Pair<String, String>> matchers;
|
||||
private final Key id;
|
||||
|
||||
public UnsafeBlockStateMatcher(Key id, List<Pair<String, String>> matchers) {
|
||||
this.id = id;
|
||||
this.matchers = matchers;
|
||||
}
|
||||
|
||||
public boolean matches(ImmutableBlockState state) {
|
||||
if (!state.owner().value().id.equals(this.id)) {
|
||||
return false;
|
||||
}
|
||||
CustomBlock customBlock = state.owner().value();
|
||||
for (Pair<String, String> matcher : matchers) {
|
||||
Property<?> property = customBlock.getProperty(matcher.left());
|
||||
if (property == null) {
|
||||
return false;
|
||||
}
|
||||
Comparable<?> value = state.get(property);
|
||||
String valueStr = Property.formatValue(property, value);
|
||||
if (!matcher.right().equals(valueStr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (matchers.isEmpty()) {
|
||||
return id.toString();
|
||||
}
|
||||
return id + "[" + matchers.stream()
|
||||
.map(entry -> entry.left() + "=" + entry.right())
|
||||
.collect(Collectors.joining(",")) + "]";
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
@Nullable
|
||||
public static UnsafeBlockStateMatcher deserialize(@NotNull String data) {
|
||||
StringReader reader = StringReader.simple(data);
|
||||
String blockIdString = reader.readUnquotedString();
|
||||
if (reader.canRead() && reader.peek() == ':') {
|
||||
reader.skip();
|
||||
blockIdString = blockIdString + ":" + reader.readUnquotedString();
|
||||
}
|
||||
Optional<Holder.Reference<CustomBlock>> optional = BuiltInRegistries.BLOCK.get(Key.from(blockIdString));
|
||||
if (optional.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Holder<CustomBlock> holder = optional.get();
|
||||
List<Pair<String, String>> properties = new ArrayList<>();
|
||||
if (reader.canRead() && reader.peek() == '[') {
|
||||
reader.skip();
|
||||
while (reader.canRead()) {
|
||||
reader.skipWhitespace();
|
||||
if (reader.peek() == ']') break;
|
||||
String propertyName = reader.readUnquotedString();
|
||||
reader.skipWhitespace();
|
||||
if (!reader.canRead() || reader.peek() != '=') {
|
||||
return null;
|
||||
}
|
||||
reader.skip();
|
||||
reader.skipWhitespace();
|
||||
String propertyValue = reader.readUnquotedString();
|
||||
properties.add(new Pair<>(propertyName, propertyValue));
|
||||
reader.skipWhitespace();
|
||||
if (reader.canRead() && reader.peek() == ',') {
|
||||
reader.skip();
|
||||
}
|
||||
}
|
||||
reader.skipWhitespace();
|
||||
if (reader.canRead() && reader.peek() == ']') {
|
||||
reader.skip();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new UnsafeBlockStateMatcher(holder.value().id(), properties);
|
||||
}
|
||||
}
|
||||
@@ -162,4 +162,9 @@ public abstract class Property<T extends Comparable<T>> {
|
||||
.map(it -> it.apply(property))
|
||||
.orElse(((context, state) -> ImmutableBlockState.with(state, property, property.defaultValue())));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Comparable<T>> String formatValue(Property<T> property, Comparable<?> value) {
|
||||
return property.valueName((T) value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +384,12 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
Key imageId = new Key(split[0], split[1]);
|
||||
Optional<BitmapImage> bitmapImage = bitmapImageByImageId(imageId);
|
||||
if (bitmapImage.isPresent()) {
|
||||
image = bitmapImage.get().miniMessage(Integer.parseInt(split[2]), Integer.parseInt(split[3]));
|
||||
try {
|
||||
image = bitmapImage.get().miniMessage(Integer.parseInt(split[2]), Integer.parseInt(split[3]));
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
TranslationManager.instance().log("warning.config.emoji.invalid_image", path.toString(), id.toString(), rawImage);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
TranslationManager.instance().log("warning.config.emoji.invalid_image", path.toString(), id.toString(), rawImage);
|
||||
return;
|
||||
@@ -462,15 +467,20 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
}
|
||||
}).toList();
|
||||
} else {
|
||||
String character = (String) section.get("char");
|
||||
if (character == null) {
|
||||
Object c = section.get("char");
|
||||
if (c == null) {
|
||||
TranslationManager.instance().log("warning.config.image.lack_char", path.toString(), id.toString());
|
||||
return;
|
||||
}
|
||||
if (character.length() == 1) {
|
||||
chars = List.of(character.toCharArray());
|
||||
if (c instanceof Integer integer) {
|
||||
chars = List.of(new char[]{(char) integer.intValue()});
|
||||
} else {
|
||||
chars = List.of(CharacterUtils.decodeUnicodeToChars(character));
|
||||
String character = c.toString();
|
||||
if (character.length() == 1) {
|
||||
chars = List.of(character.toCharArray());
|
||||
} else {
|
||||
chars = List.of(CharacterUtils.decodeUnicodeToChars(character));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,6 +502,10 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (codepoints.length == 0) {
|
||||
TranslationManager.instance().log("warning.config.image.lack_char", path.toString(), id.toString());
|
||||
return;
|
||||
}
|
||||
codepointGrid[i] = codepoints;
|
||||
if (size == -1) size = codepoints.length;
|
||||
if (size != codepoints.length) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface FontManager extends Manageable {
|
||||
Key DEFAULT_FONT = Key.of("minecraft:default");
|
||||
@@ -103,4 +104,6 @@ public interface FontManager extends Manageable {
|
||||
}
|
||||
|
||||
Map<String, Component> matchTags(String json);
|
||||
|
||||
void refreshEmojiSuggestions(UUID uuid);
|
||||
}
|
||||
|
||||
@@ -229,25 +229,29 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
||||
String pattern = data.get("pattern").toString().toLowerCase(Locale.ENGLISH);
|
||||
return new TrimModifier<>(material, pattern);
|
||||
}, "trim");
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
registerDataFunction((obj) -> {
|
||||
Map<String, Object> data = MiscUtils.castToMap(obj, false);
|
||||
return new ComponentModifier<>(data);
|
||||
}, "components", "component");
|
||||
registerDataFunction((obj) -> {
|
||||
List<String> data = MiscUtils.getAsStringList(obj);
|
||||
return new RemoveComponentModifier<>(data);
|
||||
}, "remove-components", "remove-component");
|
||||
}
|
||||
if (VersionHelper.isVersionNewerThan1_21()) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
registerDataFunction((obj) -> {
|
||||
String song = obj.toString();
|
||||
return new JukeboxSongModifier<>(new JukeboxPlayable(song, true));
|
||||
}, "jukebox-playable");
|
||||
}
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
registerDataFunction((obj) -> {
|
||||
String id = obj.toString();
|
||||
return new TooltipStyleModifier<>(Key.of(id));
|
||||
}, "tooltip-style");
|
||||
}
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
registerDataFunction((obj) -> {
|
||||
Map<String, Object> data = MiscUtils.castToMap(obj, false);
|
||||
return new EquippableModifier<>(EquipmentData.fromMap(data));
|
||||
|
||||
@@ -104,7 +104,7 @@ public class EquipmentData {
|
||||
map.put("dispensable", this.dispensable);
|
||||
map.put("swappable", this.swappable);
|
||||
map.put("damage_on_hurt", this.damageOnHurt);
|
||||
if (VersionHelper.isVersionNewerThan1_21_5()) {
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
map.put("equip_on_interact", this.equipOnInteract);
|
||||
}
|
||||
if (this.cameraOverlay != null) {
|
||||
|
||||
@@ -25,7 +25,7 @@ public class ItemSettings {
|
||||
|
||||
public <I> List<ItemDataModifier<I>> modifiers() {
|
||||
ArrayList<ItemDataModifier<I>> modifiers = new ArrayList<>();
|
||||
if (VersionHelper.isVersionNewerThan1_21_2() && this.equipment != null && this.equipment.modernData() != null) modifiers.add(new EquippableModifier<>(this.equipment.modernData()));
|
||||
if (VersionHelper.isOrAbove1_21_2() && this.equipment != null && this.equipment.modernData() != null) modifiers.add(new EquippableModifier<>(this.equipment.modernData()));
|
||||
// TODO 1.20 leather armor
|
||||
return modifiers;
|
||||
}
|
||||
@@ -172,7 +172,7 @@ public class ItemSettings {
|
||||
registerFactory("equippable", (value -> {
|
||||
Map<String, Object> args = MiscUtils.castToMap(value, false);
|
||||
EquipmentData data;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2() && args.containsKey("slot")) data = EquipmentData.fromMap(args);
|
||||
if (VersionHelper.isOrAbove1_21_2() && args.containsKey("slot")) data = EquipmentData.fromMap(args);
|
||||
else data = null;
|
||||
EquipmentGeneration equipment = new EquipmentGeneration(
|
||||
EquipmentGeneration.Layer.fromConfig(args.get("humanoid")),
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package net.momirealms.craftengine.core.item.modifier;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class RemoveComponentModifier<I> implements ItemDataModifier<I> {
|
||||
private final List<String> arguments;
|
||||
|
||||
public RemoveComponentModifier(List<String> arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public List<String> arguments() {
|
||||
return Collections.unmodifiableList(this.arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "remove-components";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Item<I> item, ItemBuildContext context) {
|
||||
for (String argument : arguments) {
|
||||
item.removeComponent(argument);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Item<I> item) {
|
||||
// I can't guess
|
||||
}
|
||||
}
|
||||
@@ -40,9 +40,9 @@ public abstract class AbstractRecipeManager<T> implements RecipeManager<T> {
|
||||
}
|
||||
|
||||
private VanillaRecipeReader initVanillaRecipeReader() {
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
return new VanillaRecipeReader1_21_2();
|
||||
} else if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
} else if (VersionHelper.isOrAbove1_20_5()) {
|
||||
return new VanillaRecipeReader1_20_5();
|
||||
} else {
|
||||
return new VanillaRecipeReader1_20();
|
||||
|
||||
@@ -161,7 +161,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
public static final Key KEEP_TAGS = Key.of("craftengine:keep_tags");
|
||||
|
||||
static {
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
register(KEEP_COMPONENTS, KeepComponents.FACTORY);
|
||||
} else {
|
||||
register(KEEP_TAGS, KeepTags.FACTORY);
|
||||
|
||||
@@ -10,7 +10,7 @@ import net.momirealms.craftengine.core.loot.function.LootFunction;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunctions;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.util.MCUtils;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
import net.momirealms.craftengine.core.util.MutableInt;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
@@ -64,7 +64,7 @@ public class LootPool<T> {
|
||||
private void addRandomItem(Consumer<Item<T>> lootConsumer, LootContext context) {
|
||||
Random randomSource = context.randomSource();
|
||||
List<LootEntry<T>> list = Lists.newArrayList();
|
||||
MutableInt mutableInt = new MutableInt();
|
||||
MutableInt mutableInt = new MutableInt(0);
|
||||
for (LootEntryContainer<T> lootPoolEntryContainer : this.entryContainers) {
|
||||
lootPoolEntryContainer.expand(context, (choice) -> {
|
||||
int i = choice.getWeight(context.luck());
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package net.momirealms.craftengine.core.plugin;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.AbstractExternalModel;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface CompatibilityManager {
|
||||
|
||||
void onLoad();
|
||||
|
||||
void onEnable();
|
||||
|
||||
void onDelayedEnable();
|
||||
|
||||
AbstractExternalModel createModelEngineModel(String id);
|
||||
|
||||
AbstractExternalModel createBetterModelModel(String id);
|
||||
|
||||
int interactionToBaseEntity(int id);
|
||||
|
||||
boolean hasPlaceholderAPI();
|
||||
|
||||
boolean isPluginEnabled(String plugin);
|
||||
|
||||
boolean hasPlugin(String plugin);
|
||||
|
||||
String parse(Player player, String text);
|
||||
|
||||
int getPlayerProtocolVersion(UUID uuid);
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import net.momirealms.craftengine.core.plugin.logger.filter.LogFilter;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetworkManager;
|
||||
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerAdapter;
|
||||
import net.momirealms.craftengine.core.sound.SoundManager;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.WorldManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.Logger;
|
||||
@@ -68,6 +67,7 @@ public abstract class CraftEngine implements Plugin {
|
||||
protected SoundManager soundManager;
|
||||
protected VanillaLootManager vanillaLootManager;
|
||||
protected AdvancementManager advancementManager;
|
||||
protected CompatibilityManager compatibilityManager;
|
||||
|
||||
private final Consumer<CraftEngine> reloadEventDispatcher;
|
||||
private boolean isReloading;
|
||||
@@ -82,7 +82,6 @@ public abstract class CraftEngine implements Plugin {
|
||||
protected CraftEngine(Consumer<CraftEngine> reloadEventDispatcher) {
|
||||
instance = this;
|
||||
this.reloadEventDispatcher = reloadEventDispatcher;
|
||||
VersionHelper.init(serverVersion());
|
||||
}
|
||||
|
||||
public static CraftEngine instance() {
|
||||
@@ -371,8 +370,6 @@ public abstract class CraftEngine implements Plugin {
|
||||
return isInitializing;
|
||||
}
|
||||
|
||||
public abstract boolean hasPlaceholderAPI();
|
||||
|
||||
@Override
|
||||
public DependencyManager dependencyManager() {
|
||||
return dependencyManager;
|
||||
@@ -460,4 +457,9 @@ public abstract class CraftEngine implements Plugin {
|
||||
public VanillaLootManager vanillaLootManager() {
|
||||
return vanillaLootManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatibilityManager compatibilityManager() {
|
||||
return compatibilityManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package net.momirealms.craftengine.core.plugin;
|
||||
import net.momirealms.craftengine.core.advancement.AdvancementManager;
|
||||
import net.momirealms.craftengine.core.block.BlockManager;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureManager;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
import net.momirealms.craftengine.core.item.ItemManager;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeManager;
|
||||
@@ -90,7 +89,5 @@ public interface Plugin {
|
||||
|
||||
void debug(Supplier<String> message);
|
||||
|
||||
boolean isPluginEnabled(String plugin);
|
||||
|
||||
String parse(Player player, String text);
|
||||
CompatibilityManager compatibilityManager();
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ public class Config {
|
||||
protected boolean chunk_system$restore_vanilla_blocks_on_chunk_unload;
|
||||
protected boolean chunk_system$restore_custom_blocks_on_chunk_load;
|
||||
protected boolean chunk_system$sync_custom_blocks_on_chunk_load;
|
||||
protected int chunk_system$delay_serialization;
|
||||
|
||||
protected boolean furniture$handle_invalid_furniture_on_chunk_load$enable;
|
||||
protected Map<String, String> furniture$handle_invalid_furniture_on_chunk_load$mapping;
|
||||
@@ -265,6 +266,7 @@ public class Config {
|
||||
chunk_system$restore_vanilla_blocks_on_chunk_unload = config.getBoolean("chunk-system.restore-vanilla-blocks-on-chunk-unload", true);
|
||||
chunk_system$restore_custom_blocks_on_chunk_load = config.getBoolean("chunk-system.restore-custom-blocks-on-chunk-load", true);
|
||||
chunk_system$sync_custom_blocks_on_chunk_load = config.getBoolean("chunk-system.sync-custom-blocks-on-chunk-load", false);
|
||||
chunk_system$delay_serialization = config.getInt("chunk-system.delay-serialization", 20);
|
||||
|
||||
// furniture
|
||||
furniture$handle_invalid_furniture_on_chunk_load$enable = config.getBoolean("furniture.handle-invalid-furniture-on-chunk-load.enable", false);
|
||||
@@ -683,6 +685,10 @@ public class Config {
|
||||
return instance.furniture$collision_entity_type;
|
||||
}
|
||||
|
||||
public static int delaySerialization() {
|
||||
return instance.chunk_system$delay_serialization;
|
||||
}
|
||||
|
||||
public YamlDocument loadOrCreateYamlData(String fileName) {
|
||||
File file = new File(this.plugin.dataFolderFile(), fileName);
|
||||
if (!file.exists()) {
|
||||
|
||||
@@ -406,7 +406,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, result, e.gui(), 0);
|
||||
}
|
||||
@@ -415,7 +415,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -489,7 +489,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
@@ -498,7 +498,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -522,7 +522,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
@@ -531,7 +531,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -555,7 +555,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
@@ -564,7 +564,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -613,7 +613,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, result, e.gui(), 0);
|
||||
}
|
||||
@@ -622,7 +622,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -649,7 +649,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
@@ -658,7 +658,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -746,7 +746,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, result, e.gui(), 0);
|
||||
}
|
||||
@@ -755,7 +755,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -788,7 +788,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
@@ -797,7 +797,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -891,7 +891,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, result, e.gui(), 0);
|
||||
}
|
||||
@@ -900,7 +900,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -983,7 +983,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
@@ -992,7 +992,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -1026,7 +1026,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
@@ -1035,7 +1035,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, depth + 1, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -51,4 +51,12 @@ public interface NetWorkUser {
|
||||
void setClientModState(boolean enable);
|
||||
|
||||
void addResourcePackUUID(UUID uuid);
|
||||
|
||||
ProtocolVersion protocolVersion();
|
||||
|
||||
void setProtocolVersion(int protocolVersion);
|
||||
|
||||
boolean sentResourcePack();
|
||||
|
||||
void setSentResourcePack(boolean sentResourcePack);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.List;
|
||||
|
||||
public interface NetworkManager extends Manageable {
|
||||
String MOD_CHANNEL = "craftengine:payload";
|
||||
String VIA_CHANNEL = "vv:proxy_details";
|
||||
|
||||
void setUser(Channel channel, NetWorkUser user);
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package net.momirealms.craftengine.core.plugin.network;
|
||||
|
||||
public enum ProtocolVersion {
|
||||
UNKNOWN(-1, "Unknown"),
|
||||
V1_20(763, "1.20"),
|
||||
V1_20_1(763, "1.20.1"),
|
||||
V1_20_2(764, "1.20.2"),
|
||||
V1_20_3(765, "1.20.3"),
|
||||
V1_20_4(765, "1.20.4"),
|
||||
V1_20_5(766, "1.20.5"),
|
||||
V1_20_6(766, "1.20.6"),
|
||||
V1_21(767, "1.21"),
|
||||
V1_21_1(767, "1.21.1"),
|
||||
V1_21_2(768, "1.21.2"),
|
||||
V1_21_3(768, "1.21.3"),
|
||||
V1_21_4(769, "1.21.4"),
|
||||
V1_21_5(770, "1.21.5");
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
|
||||
ProtocolVersion(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static ProtocolVersion getByName(String name) {
|
||||
for (ProtocolVersion version : values()) {
|
||||
if (version.getName().equals(name)) {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public static ProtocolVersion getById(int id) {
|
||||
for (ProtocolVersion version : values()) {
|
||||
if (version.getId() == id) {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user