mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
11
README.md
11
README.md
@@ -6,14 +6,11 @@
|
|||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/Xiao-MoMi/craft-engine/">
|
|
||||||
<img src="https://sloc.xyz/github/Xiao-MoMi/craft-engine/?category=code" alt="Scc Count Badge"/>
|
|
||||||
</a>
|
|
||||||
<a href="https://deepwiki.com/Xiao-MoMi/craft-engine">
|
<a href="https://deepwiki.com/Xiao-MoMi/craft-engine">
|
||||||
<img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki">
|
<img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine" alt="GitBook">
|
<a href="https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine" alt="GitBook">
|
||||||
<img src="https://img.shields.io/badge/Docs-User Manual-D2691E" alt="Gitbook"/>
|
<img src="https://img.shields.io/badge/📙-User Manual-D2691E" alt="Gitbook"/>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -55,7 +52,7 @@ The code you contribute will be open-sourced under the GPLv3 license. If you pre
|
|||||||
### 🌍 Translations
|
### 🌍 Translations
|
||||||
1. Clone this repository.
|
1. Clone this repository.
|
||||||
2. Create a new language file in: `/common-files/src/main/resources/translations`
|
2. Create a new language file in: `/common-files/src/main/resources/translations`
|
||||||
3. Once done, submit a **pull request** for review. We appreciate your contributions!
|
3. Once done, submit a **pull request** to **dev** branch for review. We appreciate your contributions!
|
||||||
|
|
||||||
## Differences Between Versions
|
## Differences Between Versions
|
||||||
| Version | Official Support | Max Players | Dev Builds |
|
| Version | Official Support | Max Players | Dev Builds |
|
||||||
@@ -79,7 +76,7 @@ repositories {
|
|||||||
```
|
```
|
||||||
```kotlin
|
```kotlin
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("net.momirealms:craft-engine-core:0.0.56")
|
compileOnly("net.momirealms:craft-engine-core:0.0.57")
|
||||||
compileOnly("net.momirealms:craft-engine-bukkit:0.0.56")
|
compileOnly("net.momirealms:craft-engine-bukkit:0.0.57")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -27,7 +27,7 @@ subprojects {
|
|||||||
expand(rootProject.properties)
|
expand(rootProject.properties)
|
||||||
}
|
}
|
||||||
|
|
||||||
filesMatching(arrayListOf("commands.yml", "config.yml", "*/*.yml", "ignite.mod.json")) {
|
filesMatching(arrayListOf("commands.yml", "config.yml")) {
|
||||||
expand(
|
expand(
|
||||||
Pair("project_version", rootProject.properties["project_version"]),
|
Pair("project_version", rootProject.properties["project_version"]),
|
||||||
Pair("config_version", rootProject.properties["config_version"]),
|
Pair("config_version", rootProject.properties["config_version"]),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ repositories {
|
|||||||
maven("https://repo.rapture.pw/repository/maven-releases/") // slime world
|
maven("https://repo.rapture.pw/repository/maven-releases/") // slime world
|
||||||
maven("https://repo.infernalsuite.com/repository/maven-snapshots/") // slime world
|
maven("https://repo.infernalsuite.com/repository/maven-snapshots/") // slime world
|
||||||
maven("https://repo.momirealms.net/releases/")
|
maven("https://repo.momirealms.net/releases/")
|
||||||
maven("https://mvn.lumine.io/repository/maven-public/") // model engine
|
maven("https://mvn.lumine.io/repository/maven-public/") // model engine mythic mobs
|
||||||
maven("https://nexus.phoenixdevt.fr/repository/maven-public/") // mmoitems
|
maven("https://nexus.phoenixdevt.fr/repository/maven-public/") // mmoitems
|
||||||
maven("https://repo.viaversion.com") // via
|
maven("https://repo.viaversion.com") // via
|
||||||
maven("https://repo.skriptlang.org/releases/") // skript
|
maven("https://repo.skriptlang.org/releases/") // skript
|
||||||
@@ -47,6 +47,8 @@ dependencies {
|
|||||||
compileOnly(platform("com.intellectualsites.bom:bom-newest:1.52"))
|
compileOnly(platform("com.intellectualsites.bom:bom-newest:1.52"))
|
||||||
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core")
|
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core")
|
||||||
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit") { isTransitive = false }
|
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit") { isTransitive = false }
|
||||||
|
// MythicMobs
|
||||||
|
compileOnly("io.lumine:Mythic-Dist:5.9.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ package net.momirealms.craftengine.bukkit.compatibility;
|
|||||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.bettermodel.BetterModelModel;
|
import net.momirealms.craftengine.bukkit.compatibility.bettermodel.BetterModelModel;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.item.MMOItemsProvider;
|
import net.momirealms.craftengine.bukkit.compatibility.item.MMOItemsProvider;
|
||||||
|
import net.momirealms.craftengine.bukkit.compatibility.item.MythicMobsProvider;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsProvider;
|
import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsProvider;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.legacy.slimeworld.LegacySlimeFormatStorageAdaptor;
|
import net.momirealms.craftengine.bukkit.compatibility.legacy.slimeworld.LegacySlimeFormatStorageAdaptor;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.leveler.AuraSkillsLevelerProvider;
|
import net.momirealms.craftengine.bukkit.compatibility.leveler.AuraSkillsLevelerProvider;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineModel;
|
import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineModel;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineUtils;
|
import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.compatibility.mythicmobs.MythicMobsListener;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.papi.PlaceholderAPIUtils;
|
import net.momirealms.craftengine.bukkit.compatibility.papi.PlaceholderAPIUtils;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.permission.LuckPermsEventListeners;
|
import net.momirealms.craftengine.bukkit.compatibility.permission.LuckPermsEventListeners;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.skript.SkriptHook;
|
import net.momirealms.craftengine.bukkit.compatibility.skript.SkriptHook;
|
||||||
@@ -104,6 +106,12 @@ public class BukkitCompatibilityManager implements CompatibilityManager {
|
|||||||
}
|
}
|
||||||
if (this.isPluginEnabled("AuraSkills")) {
|
if (this.isPluginEnabled("AuraSkills")) {
|
||||||
this.registerLevelerProvider("AuraSkills", new AuraSkillsLevelerProvider());
|
this.registerLevelerProvider("AuraSkills", new AuraSkillsLevelerProvider());
|
||||||
|
logHook("AuraSkills");
|
||||||
|
}
|
||||||
|
if (this.isPluginEnabled("MythicMobs")) {
|
||||||
|
BukkitItemManager.instance().registerExternalItemProvider(new MythicMobsProvider());
|
||||||
|
new MythicMobsListener(this.plugin);
|
||||||
|
logHook("MythicMobs");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.compatibility.item;
|
||||||
|
|
||||||
|
import io.lumine.mythic.bukkit.MythicBukkit;
|
||||||
|
import net.momirealms.craftengine.core.item.ExternalItemProvider;
|
||||||
|
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class MythicMobsProvider implements ExternalItemProvider<ItemStack> {
|
||||||
|
private MythicBukkit mythicBukkit;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String plugin() {
|
||||||
|
return "MythicMobs";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ItemStack build(String id, ItemBuildContext context) {
|
||||||
|
if (mythicBukkit == null || mythicBukkit.isClosed()) {
|
||||||
|
this.mythicBukkit = MythicBukkit.inst();
|
||||||
|
}
|
||||||
|
return mythicBukkit.getItemManager().getItemStack(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.compatibility.mythicmobs;
|
||||||
|
|
||||||
|
import io.lumine.mythic.api.adapters.AbstractItemStack;
|
||||||
|
import io.lumine.mythic.api.adapters.AbstractPlayer;
|
||||||
|
import io.lumine.mythic.api.config.MythicLineConfig;
|
||||||
|
import io.lumine.mythic.api.drops.DropMetadata;
|
||||||
|
import io.lumine.mythic.api.drops.IItemDrop;
|
||||||
|
import io.lumine.mythic.api.skills.SkillCaster;
|
||||||
|
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||||
|
import io.lumine.mythic.bukkit.adapters.BukkitItemStack;
|
||||||
|
import io.lumine.mythic.core.drops.droppables.ItemDrop;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
|
import net.momirealms.craftengine.core.item.CustomItem;
|
||||||
|
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||||
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
|
import net.momirealms.craftengine.core.util.MCUtils;
|
||||||
|
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
|
public class CraftEngineItemDrop extends ItemDrop implements IItemDrop {
|
||||||
|
private final CustomItem<ItemStack> customItem;
|
||||||
|
private static final Constructor<?> constructor$BukkitItemStack = ReflectionUtils.getConstructor(BukkitItemStack.class, ItemStack.class);
|
||||||
|
private static final boolean useReflection = constructor$BukkitItemStack != null;
|
||||||
|
|
||||||
|
public CraftEngineItemDrop(String line, MythicLineConfig config, CustomItem<ItemStack> customItem) {
|
||||||
|
super(line, config);
|
||||||
|
this.customItem = customItem;
|
||||||
|
CraftEngine.instance().debug(() -> "[MM调试] " + customItem.id() + " 注册成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractItemStack getDrop(DropMetadata dropMetadata, double amount) {
|
||||||
|
CraftEngine.instance().debug(() -> "[MM调试] getDrop() dropMetadata={" + dropMetadata + "}, amount={" + amount + "}");
|
||||||
|
ItemBuildContext context = ItemBuildContext.EMPTY;
|
||||||
|
SkillCaster caster = dropMetadata.getCaster();
|
||||||
|
if (caster != null && caster.getEntity() instanceof AbstractPlayer abstractPlayer) {
|
||||||
|
Entity bukkitEntity = abstractPlayer.getBukkitEntity();
|
||||||
|
if (bukkitEntity instanceof Player bukkitPlayer) {
|
||||||
|
var player = BukkitCraftEngine.instance().adapt(bukkitPlayer);
|
||||||
|
context = ItemBuildContext.of(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int amountInt = MCUtils.fastFloor(amount + 0.5F);
|
||||||
|
ItemStack itemStack = this.customItem.buildItemStack(context, amountInt);
|
||||||
|
return adapt(itemStack).amount(amountInt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AbstractItemStack adapt(ItemStack itemStack) {
|
||||||
|
if (useReflection) {
|
||||||
|
try {
|
||||||
|
return (AbstractItemStack) constructor$BukkitItemStack.newInstance(itemStack);
|
||||||
|
} catch (Exception e) {
|
||||||
|
CraftEngine.instance().logger().warn("adapt(ItemStack itemStack) error: " + e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return BukkitAdapter.adapt(itemStack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.compatibility.mythicmobs;
|
||||||
|
|
||||||
|
import io.lumine.mythic.api.config.MythicLineConfig;
|
||||||
|
import io.lumine.mythic.bukkit.events.MythicDropLoadEvent;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
|
public class MythicMobsListener implements Listener {
|
||||||
|
private final BukkitCraftEngine plugin;
|
||||||
|
|
||||||
|
public MythicMobsListener(BukkitCraftEngine plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
Bukkit.getPluginManager().registerEvents(this, plugin.javaPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onMythicDropLoad(MythicDropLoadEvent event) {
|
||||||
|
if (!event.getDropName().equalsIgnoreCase("craftengine")) return;
|
||||||
|
String argument = event.getArgument();
|
||||||
|
plugin.debug(() -> "[MM调试] " + argument);
|
||||||
|
Key itemId = Key.of(argument);
|
||||||
|
this.plugin.itemManager().getCustomItem(itemId).ifPresent(customItem -> {
|
||||||
|
String line = event.getContainer().getConfigLine();
|
||||||
|
MythicLineConfig config = event.getConfig();
|
||||||
|
event.register(new CraftEngineItemDrop(line, config, customItem));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,6 +59,8 @@ public class ImageExpansion extends PlaceholderExpansion {
|
|||||||
int codepoint;
|
int codepoint;
|
||||||
if (param.length == 4) {
|
if (param.length == 4) {
|
||||||
codepoint = image.codepointAt(Integer.parseInt(param[2]), Integer.parseInt(param[3]));
|
codepoint = image.codepointAt(Integer.parseInt(param[2]), Integer.parseInt(param[3]));
|
||||||
|
} else if (param.length == 3) {
|
||||||
|
codepoint = image.codepointAt(Integer.parseInt(param[2]), 0);
|
||||||
} else if (param.length == 2) {
|
} else if (param.length == 2) {
|
||||||
codepoint = image.codepointAt(0,0);
|
codepoint = image.codepointAt(0,0);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -7,14 +7,13 @@ import ch.njol.skript.lang.SkriptParser;
|
|||||||
import ch.njol.skript.lang.util.SimpleExpression;
|
import ch.njol.skript.lang.util.SimpleExpression;
|
||||||
import ch.njol.util.Kleenean;
|
import ch.njol.util.Kleenean;
|
||||||
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||||
|
import net.momirealms.craftengine.core.item.CustomItem;
|
||||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class ExprCustomItem extends SimpleExpression<ItemStack> {
|
public class ExprCustomItem extends SimpleExpression<ItemStack> {
|
||||||
|
|
||||||
public static void register() {
|
public static void register() {
|
||||||
@@ -36,7 +35,8 @@ public class ExprCustomItem extends SimpleExpression<ItemStack> {
|
|||||||
String itemId = this.itemId.getSingle(e);
|
String itemId = this.itemId.getSingle(e);
|
||||||
if (itemId == null)
|
if (itemId == null)
|
||||||
return null;
|
return null;
|
||||||
return new ItemStack[] {Objects.requireNonNull(CraftEngineItems.byId(Key.of(itemId))).buildItemStack(ItemBuildContext.EMPTY)};
|
CustomItem<ItemStack> customItem = CraftEngineItems.byId(Key.of(itemId));
|
||||||
|
return customItem == null ? null : new ItemStack[] {customItem.buildItemStack(ItemBuildContext.EMPTY)};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
|||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class ExprEntityFurnitureID extends SimplePropertyExpression<Object, String> {
|
public class ExprEntityFurnitureID extends SimplePropertyExpression<Object, String> {
|
||||||
|
|
||||||
@@ -15,8 +15,11 @@ public class ExprEntityFurnitureID extends SimplePropertyExpression<Object, Stri
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable String convert(Object object) {
|
public @Nullable String convert(Object object) {
|
||||||
if (object instanceof Entity entity && CraftEngineFurniture.isFurniture(entity))
|
if (object instanceof Entity entity && CraftEngineFurniture.isFurniture(entity)) {
|
||||||
return Objects.requireNonNull(CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity)).id().toString();
|
return Optional.ofNullable(CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity))
|
||||||
|
.map(it -> it.id().toString())
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,27 +71,47 @@ paper {
|
|||||||
required = false
|
required = false
|
||||||
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
|
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
|
||||||
}
|
}
|
||||||
register("NeigeItems") {
|
register("LuckPerms") { required = false }
|
||||||
required = false
|
register("ViaVersion") { required = false }
|
||||||
}
|
|
||||||
register("MMOItems") {
|
// external models
|
||||||
required = false
|
register("ModelEngine") { required = false }
|
||||||
}
|
register("BetterModel") { required = false }
|
||||||
register("ModelEngine") {
|
|
||||||
required = false
|
// external items
|
||||||
}
|
register("NeigeItems") { required = false }
|
||||||
register("BetterModel") {
|
register("MMOItems") { required = false }
|
||||||
required = false
|
register("MythicMobs") { required = false }
|
||||||
}
|
|
||||||
register("AuraSkills") {
|
// leveler
|
||||||
required = false
|
register("AuraSkills") { required = false }
|
||||||
}
|
|
||||||
register("LuckPerms") {
|
// anti grief lib
|
||||||
required = false
|
register("Dominion") { required = false }
|
||||||
}
|
register("WorldGuard") { required = false }
|
||||||
register("ViaVersion") {
|
register("Kingdoms") { required = false }
|
||||||
required = false
|
register("Lands") { required = false }
|
||||||
}
|
register("IridiumSkyblock") { required = false }
|
||||||
|
register("CrashClaim") { required = false }
|
||||||
|
register("GriefDefender") { required = false }
|
||||||
|
register("HuskClaims") { required = false }
|
||||||
|
register("BentoBox") { required = false }
|
||||||
|
register("HuskTowns") { required = false }
|
||||||
|
register("PlotSquared") { required = false }
|
||||||
|
register("Residence") { required = false }
|
||||||
|
register("SuperiorSkyblock2") { required = false }
|
||||||
|
register("Towny") { required = false }
|
||||||
|
register("FabledSkyBlock") { required = false }
|
||||||
|
register("GriefPrevention") { required = false }
|
||||||
|
register("RedProtect") { required = false }
|
||||||
|
register("Landlord") { required = false }
|
||||||
|
register("uSkyBlock") { required = false }
|
||||||
|
register("XClaim") { required = false }
|
||||||
|
register("UltimateClaims") { required = false }
|
||||||
|
register("UltimateClans") { required = false }
|
||||||
|
register("PreciousStones") { required = false }
|
||||||
|
register("hClaims") { required = false }
|
||||||
|
register("Factions") { required = false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public class PaperCraftEngineBootstrap implements PluginBootstrap {
|
|||||||
new ModernEventHandler(context, this.plugin).register();
|
new ModernEventHandler(context, this.plugin).register();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
logger.info("Patching the server...");
|
||||||
RuntimePatcher.patch(this.plugin);
|
RuntimePatcher.patch(this.plugin);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Failed to patch server", e);
|
throw new RuntimeException("Failed to patch server", e);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public final class CraftEngineFurniture {
|
|||||||
public static BukkitFurniture place(Location location, Key furnitureId) {
|
public static BukkitFurniture place(Location location, Key furnitureId) {
|
||||||
CustomFurniture furniture = byId(furnitureId);
|
CustomFurniture furniture = byId(furnitureId);
|
||||||
if (furniture == null) return null;
|
if (furniture == null) return null;
|
||||||
return place(location, furnitureId, furniture.getAnyPlacement());
|
return place(location, furnitureId, furniture.getAnyAnchorType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import net.momirealms.craftengine.core.world.Vec3d;
|
|||||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@@ -371,19 +370,18 @@ public class BlockEventListener implements Listener {
|
|||||||
// for vanilla blocks
|
// for vanilla blocks
|
||||||
if (event.getChangedType() == Material.NOTE_BLOCK) {
|
if (event.getChangedType() == Material.NOTE_BLOCK) {
|
||||||
Block block = event.getBlock();
|
Block block = event.getBlock();
|
||||||
|
Block sourceBlock = event.getSourceBlock();
|
||||||
|
if (block.getX() == sourceBlock.getX() && block.getX() == sourceBlock.getZ()) {
|
||||||
World world = block.getWorld();
|
World world = block.getWorld();
|
||||||
Location location = block.getLocation();
|
Location location = block.getLocation();
|
||||||
Block sourceBlock = event.getSourceBlock();
|
|
||||||
BlockFace direction = sourceBlock.getFace(block);
|
|
||||||
if (direction == BlockFace.UP || direction == BlockFace.DOWN) {
|
|
||||||
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world);
|
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world);
|
||||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel);
|
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel);
|
||||||
Object blockPos = LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
Object blockPos = LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||||
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos);
|
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos);
|
||||||
if (direction == BlockFace.UP) {
|
if (block.getY() > sourceBlock.getY()) {
|
||||||
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, CoreReflections.instance$Direction$UP, blockPos, 0);
|
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, CoreReflections.instance$Direction$UP, blockPos, Config.maxNoteBlockChainUpdate());
|
||||||
} else {
|
} else {
|
||||||
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, CoreReflections.instance$Direction$DOWN, blockPos, 0);
|
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, CoreReflections.instance$Direction$DOWN, blockPos, Config.maxNoteBlockChainUpdate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||||
import net.momirealms.craftengine.bukkit.util.RegistryUtils;
|
import net.momirealms.craftengine.bukkit.util.RegistryUtils;
|
||||||
@@ -31,7 +32,6 @@ import net.momirealms.craftengine.core.pack.LoadingSequence;
|
|||||||
import net.momirealms.craftengine.core.pack.Pack;
|
import net.momirealms.craftengine.core.pack.Pack;
|
||||||
import net.momirealms.craftengine.core.pack.ResourceLocation;
|
import net.momirealms.craftengine.core.pack.ResourceLocation;
|
||||||
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
|
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
|
||||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||||
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
||||||
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
|
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
|
||||||
@@ -45,7 +45,6 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.Registry;
|
import org.bukkit.Registry;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -93,11 +92,9 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
this.blockParser = new BlockParser();
|
this.blockParser = new BlockParser();
|
||||||
this.initVanillaRegistry();
|
this.initVanillaRegistry();
|
||||||
this.loadMappingsAndAdditionalBlocks();
|
this.loadMappingsAndAdditionalBlocks();
|
||||||
if (!plugin.requiresRestart()) {
|
|
||||||
this.registerBlocks();
|
this.registerBlocks();
|
||||||
this.registerEmptyBlock();
|
this.registerEmptyBlock();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
@@ -163,9 +160,9 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
for (Map.Entry<Integer, List<String>> entry : this.clientBoundTags.entrySet()) {
|
for (Map.Entry<Integer, List<String>> entry : this.clientBoundTags.entrySet()) {
|
||||||
list.add(new TagUtils.TagEntry(entry.getKey(), entry.getValue()));
|
list.add(new TagUtils.TagEntry(entry.getKey(), entry.getValue()));
|
||||||
}
|
}
|
||||||
Object packet = TagUtils.createUpdateTagsPacket(Map.of(MRegistries.instance$Registries$BLOCK, list));
|
Object packet = TagUtils.createUpdateTagsPacket(Map.of(MRegistries.BLOCK, list));
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (BukkitServerPlayer player : this.plugin.networkManager().onlineUsers()) {
|
||||||
this.plugin.networkManager().sendPacket(this.plugin.adapt(player), packet);
|
player.sendPacket(packet, false);
|
||||||
}
|
}
|
||||||
// 如果空,那么新来的玩家就没必要收到更新包了
|
// 如果空,那么新来的玩家就没必要收到更新包了
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
@@ -276,19 +273,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initVanillaRegistry() {
|
private void initVanillaRegistry() {
|
||||||
int vanillaStateCount;
|
int vanillaStateCount = RegistryUtils.currentBlockRegistrySize();
|
||||||
if (this.plugin.hasMod()) {
|
|
||||||
try {
|
|
||||||
Class<?> modClass = ReflectionUtils.getClazz(CraftEngine.MOD_CLASS);
|
|
||||||
Field amountField = ReflectionUtils.getDeclaredField(modClass, "vanillaRegistrySize");
|
|
||||||
vanillaStateCount = amountField.getInt(null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
vanillaStateCount = RegistryUtils.currentBlockRegistrySize();
|
|
||||||
this.plugin.logger().severe("Fatal error", e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vanillaStateCount = RegistryUtils.currentBlockRegistrySize();
|
|
||||||
}
|
|
||||||
this.plugin.logger().info("Vanilla block count: " + vanillaStateCount);
|
this.plugin.logger().info("Vanilla block count: " + vanillaStateCount);
|
||||||
BlockStateUtils.init(vanillaStateCount);
|
BlockStateUtils.init(vanillaStateCount);
|
||||||
}
|
}
|
||||||
@@ -512,10 +497,13 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
throw new LocalizedResourceConfigException("warning.config.block.state.model.invalid_path", modelPath);
|
throw new LocalizedResourceConfigException("warning.config.block.state.model.invalid_path", modelPath);
|
||||||
}
|
}
|
||||||
json.addProperty("model", modelPath);
|
json.addProperty("model", modelPath);
|
||||||
if (singleModelMap.containsKey("x")) json.addProperty("x", ResourceConfigUtils.getAsInt(singleModelMap.get("x"), "x"));
|
if (singleModelMap.containsKey("x"))
|
||||||
if (singleModelMap.containsKey("y")) json.addProperty("y", ResourceConfigUtils.getAsInt(singleModelMap.get("y"), "y"));
|
json.addProperty("x", ResourceConfigUtils.getAsInt(singleModelMap.get("x"), "x"));
|
||||||
|
if (singleModelMap.containsKey("y"))
|
||||||
|
json.addProperty("y", ResourceConfigUtils.getAsInt(singleModelMap.get("y"), "y"));
|
||||||
if (singleModelMap.containsKey("uvlock")) json.addProperty("uvlock", (boolean) singleModelMap.get("uvlock"));
|
if (singleModelMap.containsKey("uvlock")) json.addProperty("uvlock", (boolean) singleModelMap.get("uvlock"));
|
||||||
if (singleModelMap.containsKey("weight")) json.addProperty("weight", ResourceConfigUtils.getAsInt(singleModelMap.get("weight"), "weight"));
|
if (singleModelMap.containsKey("weight"))
|
||||||
|
json.addProperty("weight", ResourceConfigUtils.getAsInt(singleModelMap.get("weight"), "weight"));
|
||||||
Map<String, Object> generationMap = MiscUtils.castToMap(singleModelMap.get("generation"), true);
|
Map<String, Object> generationMap = MiscUtils.castToMap(singleModelMap.get("generation"), true);
|
||||||
if (generationMap != null) {
|
if (generationMap != null) {
|
||||||
prepareModelGeneration(ModelGeneration.of(Key.of(modelPath), generationMap));
|
prepareModelGeneration(ModelGeneration.of(Key.of(modelPath), generationMap));
|
||||||
@@ -591,6 +579,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
Object resourceLocation = KeyUtils.toResourceLocation(BlockKeys.NOTE_BLOCK);
|
Object resourceLocation = KeyUtils.toResourceLocation(BlockKeys.NOTE_BLOCK);
|
||||||
Object block = CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.BLOCK, resourceLocation);
|
Object block = CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.BLOCK, resourceLocation);
|
||||||
Object stateDefinition = CoreReflections.field$Block$StateDefinition.get(block);
|
Object stateDefinition = CoreReflections.field$Block$StateDefinition.get(block);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
ImmutableList<Object> states = (ImmutableList<Object>) CoreReflections.field$StateDefinition$states.get(stateDefinition);
|
ImmutableList<Object> states = (ImmutableList<Object>) CoreReflections.field$StateDefinition$states.get(stateDefinition);
|
||||||
for (Object state : states) {
|
for (Object state : states) {
|
||||||
BlockStateUtils.CLIENT_SIDE_NOTE_BLOCKS.put(state, new Object());
|
BlockStateUtils.CLIENT_SIDE_NOTE_BLOCKS.put(state, new Object());
|
||||||
@@ -723,14 +712,6 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
Object blockHolder;
|
Object blockHolder;
|
||||||
Object resourceLocation = createResourceLocation(realBlockKey);
|
Object resourceLocation = createResourceLocation(realBlockKey);
|
||||||
|
|
||||||
if (this.plugin.hasMod()) {
|
|
||||||
newRealBlock = CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.BLOCK, resourceLocation);
|
|
||||||
newBlockState = getOnlyBlockState(newRealBlock);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Optional<Object> optionalHolder = (Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(MBuiltInRegistries.BLOCK, CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.instance$Registries$BLOCK, resourceLocation));
|
|
||||||
blockHolder = optionalHolder.get();
|
|
||||||
} else {
|
|
||||||
try {
|
try {
|
||||||
newRealBlock = BlockGenerator.generateBlock(clientSideBlockType, clientSideBlock, blockProperties);
|
newRealBlock = BlockGenerator.generateBlock(clientSideBlockType, clientSideBlock, blockProperties);
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
@@ -744,7 +725,6 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
|
|
||||||
newBlockState = getOnlyBlockState(newRealBlock);
|
newBlockState = getOnlyBlockState(newRealBlock);
|
||||||
CoreReflections.method$IdMapper$add.invoke(CoreReflections.instance$Block$BLOCK_STATE_REGISTRY, newBlockState);
|
CoreReflections.method$IdMapper$add.invoke(CoreReflections.instance$Block$BLOCK_STATE_REGISTRY, newBlockState);
|
||||||
}
|
|
||||||
|
|
||||||
if (isNoteBlock) {
|
if (isNoteBlock) {
|
||||||
BlockStateUtils.CLIENT_SIDE_NOTE_BLOCKS.put(newBlockState, new Object());
|
BlockStateUtils.CLIENT_SIDE_NOTE_BLOCKS.put(newBlockState, new Object());
|
||||||
@@ -782,7 +762,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
private Object createBlockProperties(Key realBlockKey) throws Exception {
|
private Object createBlockProperties(Key realBlockKey) throws Exception {
|
||||||
Object blockProperties = CoreReflections.method$BlockBehaviour$Properties$of.invoke(null);
|
Object blockProperties = CoreReflections.method$BlockBehaviour$Properties$of.invoke(null);
|
||||||
Object realBlockResourceLocation = createResourceLocation(realBlockKey);
|
Object realBlockResourceLocation = createResourceLocation(realBlockKey);
|
||||||
Object realBlockResourceKey = CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.instance$Registries$BLOCK, realBlockResourceLocation);
|
Object realBlockResourceKey = CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.BLOCK, realBlockResourceLocation);
|
||||||
if (CoreReflections.field$BlockBehaviour$Properties$id != null) {
|
if (CoreReflections.field$BlockBehaviour$Properties$id != null) {
|
||||||
CoreReflections.field$BlockBehaviour$Properties$id.set(blockProperties, realBlockResourceKey);
|
CoreReflections.field$BlockBehaviour$Properties$id.set(blockProperties, realBlockResourceKey);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,13 +129,12 @@ public class BukkitCustomBlock extends AbstractCustomBlock {
|
|||||||
// init cache
|
// init cache
|
||||||
CoreReflections.method$BlockStateBase$initCache.invoke(mcBlockState);
|
CoreReflections.method$BlockStateBase$initCache.invoke(mcBlockState);
|
||||||
// set block light
|
// set block light
|
||||||
if (settings.blockLight() != -1) {
|
int blockLight = settings.blockLight() != -1 ? settings.blockLight() : CoreReflections.field$BlockStateBase$lightBlock.getInt(state.vanillaBlockState().handle());
|
||||||
if (VersionHelper.isOrAbove1_21_2()) {
|
if (VersionHelper.isOrAbove1_21_2()) {
|
||||||
CoreReflections.field$BlockStateBase$lightBlock.set(mcBlockState, settings.blockLight());
|
CoreReflections.field$BlockStateBase$lightBlock.set(mcBlockState, blockLight);
|
||||||
} else {
|
} else {
|
||||||
Object cache = CoreReflections.field$BlockStateBase$cache.get(mcBlockState);
|
Object cache = CoreReflections.field$BlockStateBase$cache.get(mcBlockState);
|
||||||
CoreReflections.field$BlockStateBase$Cache$lightBlock.set(cache, settings.blockLight());
|
CoreReflections.field$BlockStateBase$Cache$lightBlock.set(cache, blockLight);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// set fluid later
|
// set fluid later
|
||||||
if (settings.fluidState()) {
|
if (settings.fluidState()) {
|
||||||
@@ -151,7 +150,7 @@ public class BukkitCustomBlock extends AbstractCustomBlock {
|
|||||||
Object holder = BukkitCraftEngine.instance().blockManager().getMinecraftBlockHolder(state.customBlockState().registryId());
|
Object holder = BukkitCraftEngine.instance().blockManager().getMinecraftBlockHolder(state.customBlockState().registryId());
|
||||||
Set<Object> tags = new HashSet<>();
|
Set<Object> tags = new HashSet<>();
|
||||||
for (Key tag : settings.tags()) {
|
for (Key tag : settings.tags()) {
|
||||||
tags.add(CoreReflections.method$TagKey$create.invoke(null, MRegistries.instance$Registries$BLOCK, KeyUtils.toResourceLocation(tag)));
|
tags.add(CoreReflections.method$TagKey$create.invoke(null, MRegistries.BLOCK, KeyUtils.toResourceLocation(tag)));
|
||||||
}
|
}
|
||||||
CoreReflections.field$Holder$Reference$tags.set(holder, tags);
|
CoreReflections.field$Holder$Reference$tags.set(holder, tags);
|
||||||
// set burning properties
|
// set burning properties
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio
|
|||||||
public void onPlace(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
public void onPlace(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||||
Object world = args[1];
|
Object world = args[1];
|
||||||
Object blockPos = args[2];
|
Object blockPos = args[2];
|
||||||
CoreReflections.method$LevelAccessor$scheduleTick.invoke(world, blockPos, thisBlock, 2);
|
FastNMS.INSTANCE.method$LevelAccessor$scheduleTick(world, blockPos, thisBlock, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,7 +86,7 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
if (this.delay != 0) {
|
if (this.delay != 0) {
|
||||||
CoreReflections.method$LevelAccessor$scheduleTick.invoke(level, blockPos, thisBlock, this.delay);
|
FastNMS.INSTANCE.method$LevelAccessor$scheduleTick(level, blockPos, thisBlock, this.delay);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
if (!canSurvive(thisBlock, new Object[] {state, level, blockPos}, () -> true)) {
|
if (!canSurvive(thisBlock, new Object[] {state, level, blockPos}, () -> true)) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
|
|||||||
public void onPlace(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
public void onPlace(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||||
Object world = args[1];
|
Object world = args[1];
|
||||||
Object blockPos = args[2];
|
Object blockPos = args[2];
|
||||||
CoreReflections.method$LevelAccessor$scheduleTick.invoke(world, blockPos, thisBlock, 2);
|
FastNMS.INSTANCE.method$LevelAccessor$scheduleTick(world, blockPos, thisBlock, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -50,7 +50,7 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
|
|||||||
world = args[3];
|
world = args[3];
|
||||||
blockPos = args[4];
|
blockPos = args[4];
|
||||||
}
|
}
|
||||||
CoreReflections.method$LevelAccessor$scheduleTick.invoke(world, blockPos, thisBlock, 2);
|
FastNMS.INSTANCE.method$LevelAccessor$scheduleTick(world, blockPos, thisBlock, 2);
|
||||||
return args[0];
|
return args[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class LampBlockBehavior extends BukkitBlockBehavior {
|
|||||||
boolean lit = state.get(this.litProperty);
|
boolean lit = state.get(this.litProperty);
|
||||||
if (lit != FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
|
if (lit != FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
|
||||||
if (lit) {
|
if (lit) {
|
||||||
CoreReflections.method$LevelAccessor$scheduleTick.invoke(world, blockPos, thisBlock, 4);
|
FastNMS.INSTANCE.method$LevelAccessor$scheduleTick(world, blockPos, thisBlock, 4);
|
||||||
} else {
|
} else {
|
||||||
// TODO Call Event
|
// TODO Call Event
|
||||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2);
|
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2);
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
|||||||
LeavesBlockBehavior behavior = optionalBehavior.get();
|
LeavesBlockBehavior behavior = optionalBehavior.get();
|
||||||
int distance = behavior.getDistanceAt(neighborState) + 1;
|
int distance = behavior.getDistanceAt(neighborState) + 1;
|
||||||
if (distance != 1 || behavior.getDistance(thisState) != distance) {
|
if (distance != 1 || behavior.getDistance(thisState) != distance) {
|
||||||
CoreReflections.method$LevelAccessor$scheduleTick.invoke(world, blockPos, thisBlock, 1);
|
FastNMS.INSTANCE.method$LevelAccessor$scheduleTick(world, blockPos, thisBlock, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateTree(Object world, Object blockPos, Object blockState, Object randomSource) throws Exception {
|
private void generateTree(Object world, Object blockPos, Object blockState, Object randomSource) throws Exception {
|
||||||
Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.instance$Registries$CONFIGURED_FEATURE);
|
Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.CONFIGURED_FEATURE);
|
||||||
if (registry == null) return;
|
if (registry == null) return;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Optional<Object> holder = (Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(registry, FeatureUtils.createFeatureKey(treeFeature()));
|
Optional<Object> holder = (Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(registry, FeatureUtils.createFeatureKey(treeFeature()));
|
||||||
|
|||||||
@@ -7,20 +7,21 @@ public interface EntityData<T> {
|
|||||||
Object serializer();
|
Object serializer();
|
||||||
int id();
|
int id();
|
||||||
T defaultValue();
|
T defaultValue();
|
||||||
|
Object entityDataAccessor();
|
||||||
|
|
||||||
default Object createEntityDataIfNotDefaultValue(T value) {
|
default Object createEntityDataIfNotDefaultValue(T value) {
|
||||||
if (defaultValue().equals(value)) return null;
|
if (defaultValue().equals(value)) return null;
|
||||||
return EntityDataValue.create(id(), serializer(), value);
|
return EntityDataValue.create(id(), serializer(), entityDataAccessor(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void addEntityDataIfNotDefaultValue(T value, List<Object> list) {
|
default void addEntityDataIfNotDefaultValue(T value, List<Object> list) {
|
||||||
if (!defaultValue().equals(value)) {
|
if (!defaultValue().equals(value)) {
|
||||||
list.add(EntityDataValue.create(id(), serializer(), value));
|
list.add(EntityDataValue.create(id(), serializer(), entityDataAccessor(), value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default void addEntityData(T value, List<Object> list) {
|
default void addEntityData(T value, List<Object> list) {
|
||||||
list.add(EntityDataValue.create(id(), serializer(), value));
|
list.add(EntityDataValue.create(id(), serializer(), entityDataAccessor(), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> EntityData<T> of(int id, Object serializer, T defaultValue) {
|
static <T> EntityData<T> of(int id, Object serializer, T defaultValue) {
|
||||||
|
|||||||
@@ -98,8 +98,7 @@ public class EntityDataValue {
|
|||||||
throw new IllegalAccessError("Utility class");
|
throw new IllegalAccessError("Utility class");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object create(int id, Object serializer, Object value) {
|
public static Object create(int id, Object serializer, Object entityDataAccessor, Object value) {
|
||||||
Object entityDataAccessor = FastNMS.INSTANCE.constructor$EntityDataAccessor(id, serializer);
|
|
||||||
return FastNMS.INSTANCE.method$SynchedEntityData$DataValue$create(entityDataAccessor, value);
|
return FastNMS.INSTANCE.method$SynchedEntityData$DataValue$create(entityDataAccessor, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
package net.momirealms.craftengine.bukkit.entity.data;
|
package net.momirealms.craftengine.bukkit.entity.data;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
|
|
||||||
public class SimpleEntityData<T> implements EntityData<T> {
|
public class SimpleEntityData<T> implements EntityData<T> {
|
||||||
private final int id;
|
private final int id;
|
||||||
private final Object serializer;
|
private final Object serializer;
|
||||||
private final T defaultValue;
|
private final T defaultValue;
|
||||||
|
private final Object entityDataAccessor;
|
||||||
|
|
||||||
public SimpleEntityData(int id, Object serializer, T defaultValue) {
|
public SimpleEntityData(int id, Object serializer, T defaultValue) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
|
this.entityDataAccessor = FastNMS.INSTANCE.constructor$EntityDataAccessor(id, serializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -25,4 +29,9 @@ public class SimpleEntityData<T> implements EntityData<T> {
|
|||||||
public T defaultValue() {
|
public T defaultValue() {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object entityDataAccessor() {
|
||||||
|
return entityDataAccessor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import java.util.*;
|
|||||||
public class BukkitFurniture implements Furniture {
|
public class BukkitFurniture implements Furniture {
|
||||||
private final Key id;
|
private final Key id;
|
||||||
private final CustomFurniture furniture;
|
private final CustomFurniture furniture;
|
||||||
private final AnchorType anchorType;
|
private final CustomFurniture.Placement placement;
|
||||||
private FurnitureExtraData extraData;
|
private FurnitureExtraData extraData;
|
||||||
// location
|
// location
|
||||||
private final Location location;
|
private final Location location;
|
||||||
@@ -61,7 +61,7 @@ public class BukkitFurniture implements Furniture {
|
|||||||
this.id = furniture.id();
|
this.id = furniture.id();
|
||||||
this.extraData = extraData;
|
this.extraData = extraData;
|
||||||
this.baseEntityId = baseEntity.getEntityId();
|
this.baseEntityId = baseEntity.getEntityId();
|
||||||
this.anchorType = extraData.anchorType().orElse(furniture.getAnyPlacement());
|
|
||||||
this.location = baseEntity.getLocation();
|
this.location = baseEntity.getLocation();
|
||||||
this.baseEntity = new WeakReference<>(baseEntity);
|
this.baseEntity = new WeakReference<>(baseEntity);
|
||||||
this.furniture = furniture;
|
this.furniture = furniture;
|
||||||
@@ -70,7 +70,7 @@ public class BukkitFurniture implements Furniture {
|
|||||||
List<Integer> mainEntityIds = new IntArrayList();
|
List<Integer> mainEntityIds = new IntArrayList();
|
||||||
mainEntityIds.add(this.baseEntityId);
|
mainEntityIds.add(this.baseEntityId);
|
||||||
|
|
||||||
CustomFurniture.Placement placement = furniture.getPlacement(anchorType);
|
this.placement = furniture.getValidPlacement(extraData.anchorType().orElseGet(furniture::getAnyAnchorType));
|
||||||
// bind external furniture
|
// bind external furniture
|
||||||
Optional<ExternalModel> optionalExternal = placement.externalModel();
|
Optional<ExternalModel> optionalExternal = placement.externalModel();
|
||||||
if (optionalExternal.isPresent()) {
|
if (optionalExternal.isPresent()) {
|
||||||
@@ -171,7 +171,7 @@ public class BukkitFurniture implements Furniture {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Location dropLocation() {
|
public Location dropLocation() {
|
||||||
Optional<Vector3f> dropOffset = config().getPlacement(this.anchorType).dropOffset();
|
Optional<Vector3f> dropOffset = this.placement.dropOffset();
|
||||||
if (dropOffset.isEmpty()) {
|
if (dropOffset.isEmpty()) {
|
||||||
return location();
|
return location();
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,7 @@ public class BukkitFurniture implements Furniture {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull AnchorType anchorType() {
|
public @NotNull AnchorType anchorType() {
|
||||||
return this.anchorType;
|
return this.placement.anchorType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class BukkitFurnitureElement extends AbstractFurnitureElement {
|
|||||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
entityId, UUID.randomUUID(), position.x() + offset.x, position.y() + offset.y, position.z() - offset.z, 0, position.xRot(),
|
entityId, UUID.randomUUID(), position.x() + offset.x, position.y() + offset.y, position.z() - offset.z, 0, position.xRot(),
|
||||||
MEntityTypes.instance$EntityType$ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
));
|
));
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, getCachedValues(dyedColor)));
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, getCachedValues(dyedColor)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY);
|
public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY);
|
||||||
public static final NamespacedKey FURNITURE_COLLISION = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_COLLISION);
|
public static final NamespacedKey FURNITURE_COLLISION = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_COLLISION);
|
||||||
public static Class<?> COLLISION_ENTITY_CLASS = Interaction.class;
|
public static Class<?> COLLISION_ENTITY_CLASS = Interaction.class;
|
||||||
public static Object NMS_COLLISION_ENTITY_TYPE = MEntityTypes.instance$EntityType$INTERACTION;
|
public static Object NMS_COLLISION_ENTITY_TYPE = MEntityTypes.INTERACTION;
|
||||||
public static ColliderType COLLISION_ENTITY_TYPE = ColliderType.INTERACTION;
|
public static ColliderType COLLISION_ENTITY_TYPE = ColliderType.INTERACTION;
|
||||||
private static BukkitFurnitureManager instance;
|
private static BukkitFurnitureManager instance;
|
||||||
private final BukkitCraftEngine plugin;
|
private final BukkitCraftEngine plugin;
|
||||||
@@ -70,7 +70,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
public BukkitFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) {
|
public BukkitFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) {
|
||||||
Optional<AnchorType> optionalAnchorType = extraData.anchorType();
|
Optional<AnchorType> optionalAnchorType = extraData.anchorType();
|
||||||
if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) {
|
if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) {
|
||||||
extraData.anchorType(furniture.getAnyPlacement());
|
extraData.anchorType(furniture.getAnyAnchorType());
|
||||||
}
|
}
|
||||||
Entity furnitureEntity = EntityUtils.spawnEntity(location.getWorld(), location, EntityType.ITEM_DISPLAY, entity -> {
|
Entity furnitureEntity = EntityUtils.spawnEntity(location.getWorld(), location, EntityType.ITEM_DISPLAY, entity -> {
|
||||||
ItemDisplay display = (ItemDisplay) entity;
|
ItemDisplay display = (ItemDisplay) entity;
|
||||||
@@ -92,7 +92,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
@Override
|
@Override
|
||||||
public void delayedInit() {
|
public void delayedInit() {
|
||||||
COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class;
|
COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class;
|
||||||
NMS_COLLISION_ENTITY_TYPE = Config.colliderType() == ColliderType.INTERACTION ? MEntityTypes.instance$EntityType$INTERACTION : MEntityTypes.instance$EntityType$OAK_BOAT;
|
NMS_COLLISION_ENTITY_TYPE = Config.colliderType() == ColliderType.INTERACTION ? MEntityTypes.INTERACTION : MEntityTypes.OAK_BOAT;
|
||||||
COLLISION_ENTITY_TYPE = Config.colliderType();
|
COLLISION_ENTITY_TYPE = Config.colliderType();
|
||||||
Bukkit.getPluginManager().registerEvents(this.dismountListener, this.plugin.javaPlugin());
|
Bukkit.getPluginManager().registerEvents(this.dismountListener, this.plugin.javaPlugin());
|
||||||
Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.javaPlugin());
|
Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.javaPlugin());
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class InteractionHitBox extends AbstractHitBox {
|
|||||||
float yaw = position.xRot();
|
float yaw = position.xRot();
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
entityId[0], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
|
entityId[0], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
|
||||||
MEntityTypes.instance$EntityType$INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
), true);
|
), true);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId[0], List.copyOf(this.cachedValues)), true);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId[0], List.copyOf(this.cachedValues)), true);
|
||||||
if (canUseItemOn()) {
|
if (canUseItemOn()) {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
if (interactionEntity) {
|
if (interactionEntity) {
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.005f, z - offset.z, 0, yaw,
|
entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.005f, z - offset.z, 0, yaw,
|
||||||
MEntityTypes.instance$EntityType$INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
), true);
|
), true);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
||||||
if (canUseOn) {
|
if (canUseOn) {
|
||||||
@@ -80,7 +80,7 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
if (interactionEntity) {
|
if (interactionEntity) {
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.005f - shulkerHeight + scale, z - offset.z, 0, yaw,
|
entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.005f - shulkerHeight + scale, z - offset.z, 0, yaw,
|
||||||
MEntityTypes.instance$EntityType$INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
), true);
|
), true);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
||||||
if (canUseOn) {
|
if (canUseOn) {
|
||||||
@@ -102,14 +102,14 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
// first interaction
|
// first interaction
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.005f, z - offset.z, 0, yaw,
|
entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.005f, z - offset.z, 0, yaw,
|
||||||
MEntityTypes.instance$EntityType$INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
), true);
|
), true);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
||||||
// second interaction
|
// second interaction
|
||||||
double distance = shulkerHeight - scale;
|
double distance = shulkerHeight - scale;
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
entityIds[3], UUID.randomUUID(), x + offset.x + shulkerDirection.stepX() * distance, y + offset.y - 0.005f, z - offset.z + shulkerDirection.stepZ() * distance, 0, yaw,
|
entityIds[3], UUID.randomUUID(), x + offset.x + shulkerDirection.stepX() * distance, y + offset.y - 0.005f, z - offset.z + shulkerDirection.stepZ() * distance, 0, yaw,
|
||||||
MEntityTypes.instance$EntityType$INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
), true);
|
), true);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[3], List.copyOf(cachedInteractionValues)), true);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[3], List.copyOf(cachedInteractionValues)), true);
|
||||||
if (canUseOn) {
|
if (canUseOn) {
|
||||||
@@ -213,11 +213,11 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
double processedY = (fractionalPart >= 0.5) ? integerPart + 1 : originalY;
|
double processedY = (fractionalPart >= 0.5) ? integerPart + 1 : originalY;
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
entityIds[0], UUID.randomUUID(), x + offset.x, originalY, z - offset.z, 0, yaw,
|
entityIds[0], UUID.randomUUID(), x + offset.x, originalY, z - offset.z, 0, yaw,
|
||||||
MEntityTypes.instance$EntityType$ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
), false);
|
), false);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
entityIds[1], UUID.randomUUID(), x + offset.x, processedY, z - offset.z, 0, yaw,
|
entityIds[1], UUID.randomUUID(), x + offset.x, processedY, z - offset.z, 0, yaw,
|
||||||
MEntityTypes.instance$EntityType$SHULKER, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.SHULKER, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
), false);
|
), false);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[1], List.copyOf(this.cachedShulkerValues)), false);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[1], List.copyOf(this.cachedShulkerValues)), false);
|
||||||
// add passengers
|
// add passengers
|
||||||
|
|||||||
@@ -11,4 +11,9 @@ public class BukkitCustomProjectile extends AbstractCustomProjectile {
|
|||||||
public BukkitCustomProjectile(ProjectileMeta meta, Projectile projectile, Item<ItemStack> projectileItem) {
|
public BukkitCustomProjectile(ProjectileMeta meta, Projectile projectile, Item<ItemStack> projectileItem) {
|
||||||
super(meta, new BukkitProjectile(projectile), projectileItem);
|
super(meta, new BukkitProjectile(projectile), projectileItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BukkitProjectile projectile() {
|
||||||
|
return (BukkitProjectile) super.projectile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
public class BukkitProjectileManager implements Listener, ProjectileManager {
|
public class BukkitProjectileManager implements Listener, ProjectileManager {
|
||||||
private static BukkitProjectileManager instance;
|
private static BukkitProjectileManager instance;
|
||||||
private final BukkitCraftEngine plugin;
|
private final BukkitCraftEngine plugin;
|
||||||
private final Map<Integer, BukkitCustomProjectile> projectiles;
|
// 会被netty线程访问
|
||||||
|
private final Map<Integer, BukkitCustomProjectile> projectiles = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public BukkitProjectileManager(BukkitCraftEngine plugin) {
|
public BukkitProjectileManager(BukkitCraftEngine plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.projectiles = new ConcurrentHashMap<>();
|
|
||||||
instance = this;
|
instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,8 @@ public class BukkitProjectileManager implements Listener, ProjectileManager {
|
|||||||
wrapped.getCustomItem().ifPresent(it -> {
|
wrapped.getCustomItem().ifPresent(it -> {
|
||||||
ProjectileMeta meta = it.settings().projectileMeta();
|
ProjectileMeta meta = it.settings().projectileMeta();
|
||||||
if (meta != null) {
|
if (meta != null) {
|
||||||
this.projectiles.put(projectile.getEntityId(), new BukkitCustomProjectile(meta, projectile, wrapped));
|
BukkitCustomProjectile customProjectile = new BukkitCustomProjectile(meta, projectile, wrapped);
|
||||||
|
this.projectiles.put(projectile.getEntityId(), customProjectile);
|
||||||
new ProjectileInjectTask(projectile);
|
new ProjectileInjectTask(projectile);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -161,7 +162,8 @@ public class BukkitProjectileManager implements Listener, ProjectileManager {
|
|||||||
public class ProjectileInjectTask implements Runnable {
|
public class ProjectileInjectTask implements Runnable {
|
||||||
private final Projectile projectile;
|
private final Projectile projectile;
|
||||||
private final SchedulerTask task;
|
private final SchedulerTask task;
|
||||||
private boolean injected;
|
private Object cachedServerEntity;
|
||||||
|
private int lastInjectedInterval = 0;
|
||||||
|
|
||||||
public ProjectileInjectTask(Projectile projectile) {
|
public ProjectileInjectTask(Projectile projectile) {
|
||||||
this.projectile = projectile;
|
this.projectile = projectile;
|
||||||
@@ -178,32 +180,42 @@ public class BukkitProjectileManager implements Listener, ProjectileManager {
|
|||||||
this.task.cancel();
|
this.task.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(this.projectile);
|
Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(this.projectile);
|
||||||
if (!this.injected) {
|
// 获取server entity
|
||||||
|
if (this.cachedServerEntity == null) {
|
||||||
Object trackedEntity = FastNMS.INSTANCE.field$Entity$trackedEntity(nmsEntity);
|
Object trackedEntity = FastNMS.INSTANCE.field$Entity$trackedEntity(nmsEntity);
|
||||||
if (trackedEntity == null) {
|
if (trackedEntity == null) return;
|
||||||
return;
|
Object serverEntity = FastNMS.INSTANCE.field$ChunkMap$TrackedEntity$serverEntity(trackedEntity);
|
||||||
|
if (serverEntity == null) return;
|
||||||
|
this.cachedServerEntity = serverEntity;
|
||||||
}
|
}
|
||||||
Object serverEntity = FastNMS.INSTANCE.filed$ChunkMap$TrackedEntity$serverEntity(trackedEntity);
|
|
||||||
if (serverEntity == null) {
|
boolean inGround = FastNMS.INSTANCE.method$AbstractArrow$isInGround(nmsEntity);
|
||||||
return;
|
if (canSpawnParticle(nmsEntity, inGround)) {
|
||||||
}
|
|
||||||
try {
|
|
||||||
CoreReflections.field$ServerEntity$updateInterval.set(serverEntity, 1);
|
|
||||||
this.injected = true;
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
plugin.logger().warn("Failed to update server entity tracking interval", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (canSpawnParticle(nmsEntity)) {
|
|
||||||
this.projectile.getWorld().spawnParticle(ParticleUtils.BUBBLE, this.projectile.getLocation(), 3, 0.1, 0.1, 0.1, 0);
|
this.projectile.getWorld().spawnParticle(ParticleUtils.BUBBLE, this.projectile.getLocation(), 3, 0.1, 0.1, 0.1, 0);
|
||||||
}
|
}
|
||||||
|
if (inGround) {
|
||||||
|
updateProjectileUpdateInterval(Integer.MAX_VALUE);
|
||||||
|
} else {
|
||||||
|
updateProjectileUpdateInterval(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean canSpawnParticle(Object nmsEntity) {
|
private void updateProjectileUpdateInterval(int updateInterval) {
|
||||||
|
if (this.lastInjectedInterval == updateInterval) return;
|
||||||
|
try {
|
||||||
|
CoreReflections.methodHandle$ServerEntity$updateIntervalSetter.invokeExact(this.cachedServerEntity, updateInterval);
|
||||||
|
this.lastInjectedInterval = updateInterval;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
BukkitProjectileManager.this.plugin.logger().warn("Failed to update server entity update interval for " + this.projectile.getType().getKey() + "[" + this.projectile.getUniqueId() + "]", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean canSpawnParticle(Object nmsEntity, boolean inGround) {
|
||||||
if (!FastNMS.INSTANCE.field$Entity$wasTouchingWater(nmsEntity)) return false;
|
if (!FastNMS.INSTANCE.field$Entity$wasTouchingWater(nmsEntity)) return false;
|
||||||
if (CoreReflections.clazz$AbstractArrow.isInstance(nmsEntity)) {
|
if (CoreReflections.clazz$AbstractArrow.isInstance(nmsEntity)) {
|
||||||
return !FastNMS.INSTANCE.method$AbstractArrow$isInGround(nmsEntity);
|
return !inGround;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package net.momirealms.craftengine.bukkit.item;
|
package net.momirealms.craftengine.bukkit.item;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
|
||||||
import net.momirealms.craftengine.core.item.*;
|
import net.momirealms.craftengine.core.item.*;
|
||||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||||
@@ -10,7 +10,6 @@ import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
|||||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||||
import net.momirealms.craftengine.core.registry.Holder;
|
import net.momirealms.craftengine.core.registry.Holder;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -19,22 +18,23 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||||
private final Material material;
|
private final Object item;
|
||||||
|
private final Object clientItem;
|
||||||
|
|
||||||
public BukkitCustomItem(Holder<Key> id, Key materialKey, Material material,
|
public BukkitCustomItem(Holder<Key> id, Object item, Object clientItem, Key materialKey, Key clientBoundMaterialKey,
|
||||||
List<ItemBehavior> behaviors,
|
List<ItemBehavior> behaviors,
|
||||||
List<ItemDataModifier<ItemStack>> modifiers, List<ItemDataModifier<ItemStack>> clientBoundModifiers,
|
List<ItemDataModifier<ItemStack>> modifiers, List<ItemDataModifier<ItemStack>> clientBoundModifiers,
|
||||||
ItemSettings settings,
|
ItemSettings settings,
|
||||||
Map<EventTrigger, List<Function<PlayerOptionalContext>>> events) {
|
Map<EventTrigger, List<Function<PlayerOptionalContext>>> events) {
|
||||||
super(id, materialKey, behaviors, modifiers, clientBoundModifiers, settings, events);
|
super(id, materialKey, clientBoundMaterialKey, behaviors, modifiers, clientBoundModifiers, settings, events);
|
||||||
this.material = material;
|
this.item = item;
|
||||||
|
this.clientItem = clientItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack buildItemStack(ItemBuildContext context, int count) {
|
public ItemStack buildItemStack(ItemBuildContext context, int count) {
|
||||||
ItemStack item = new ItemStack(this.material);
|
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(this.item, count));
|
||||||
Item<ItemStack> wrapped = BukkitCraftEngine.instance().itemManager().wrap(item);
|
Item<ItemStack> wrapped = BukkitCraftEngine.instance().itemManager().wrap(item);
|
||||||
wrapped.count(count);
|
|
||||||
for (ItemDataModifier<ItemStack> modifier : this.modifiers) {
|
for (ItemDataModifier<ItemStack> modifier : this.modifiers) {
|
||||||
modifier.apply(wrapped, context);
|
modifier.apply(wrapped, context);
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Item<ItemStack> buildItem(ItemBuildContext context) {
|
public Item<ItemStack> buildItem(ItemBuildContext context) {
|
||||||
ItemStack item = new ItemStack(this.material);
|
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(this.item, 1));
|
||||||
Item<ItemStack> wrapped = BukkitCraftEngine.instance().itemManager().wrap(item);
|
Item<ItemStack> wrapped = BukkitCraftEngine.instance().itemManager().wrap(item);
|
||||||
for (ItemDataModifier<ItemStack> modifier : dataModifiers()) {
|
for (ItemDataModifier<ItemStack> modifier : dataModifiers()) {
|
||||||
modifier.apply(wrapped, context);
|
modifier.apply(wrapped, context);
|
||||||
@@ -51,23 +51,33 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
|||||||
return BukkitCraftEngine.instance().itemManager().wrap(wrapped.load());
|
return BukkitCraftEngine.instance().itemManager().wrap(wrapped.load());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder<ItemStack> builder(Material material) {
|
public Object clientItem() {
|
||||||
return new BuilderImpl(material);
|
return clientItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object item() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder<ItemStack> builder(Object item, Object clientBoundItem) {
|
||||||
|
return new BuilderImpl(item, clientBoundItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BuilderImpl implements Builder<ItemStack> {
|
public static class BuilderImpl implements Builder<ItemStack> {
|
||||||
private Holder<Key> id;
|
private Holder<Key> id;
|
||||||
private Key materialKey;
|
private Key itemKey;
|
||||||
private final Material material;
|
private final Object item;
|
||||||
|
private Key clientBoundItemKey;
|
||||||
|
private final Object clientBoundItem;
|
||||||
private final Map<EventTrigger, List<Function<PlayerOptionalContext>>> events = new EnumMap<>(EventTrigger.class);
|
private final Map<EventTrigger, List<Function<PlayerOptionalContext>>> events = new EnumMap<>(EventTrigger.class);
|
||||||
private final List<ItemBehavior> behaviors = new ArrayList<>(4);
|
private final List<ItemBehavior> behaviors = new ArrayList<>(4);
|
||||||
private final List<ItemDataModifier<ItemStack>> modifiers = new ArrayList<>(4);
|
private final List<ItemDataModifier<ItemStack>> modifiers = new ArrayList<>(4);
|
||||||
private final List<ItemDataModifier<ItemStack>> clientBoundModifiers = new ArrayList<>(4);
|
private final List<ItemDataModifier<ItemStack>> clientBoundModifiers = new ArrayList<>(4);
|
||||||
private ItemSettings settings;
|
private ItemSettings settings;
|
||||||
|
|
||||||
public BuilderImpl(Material material) {
|
public BuilderImpl(Object item, Object clientBoundItem) {
|
||||||
this.material = material;
|
this.item = item;
|
||||||
this.materialKey = KeyUtils.namespacedKey2Key(material.getKey());
|
this.clientBoundItem = clientBoundItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -76,9 +86,15 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder<ItemStack> clientBoundMaterial(Key clientBoundMaterial) {
|
||||||
|
this.clientBoundItemKey = clientBoundMaterial;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder<ItemStack> material(Key material) {
|
public Builder<ItemStack> material(Key material) {
|
||||||
this.materialKey = material;
|
this.itemKey = material;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +149,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
|||||||
@Override
|
@Override
|
||||||
public CustomItem<ItemStack> build() {
|
public CustomItem<ItemStack> build() {
|
||||||
this.modifiers.addAll(this.settings.modifiers());
|
this.modifiers.addAll(this.settings.modifiers());
|
||||||
return new BukkitCustomItem(this.id, this.materialKey, this.material, List.copyOf(this.behaviors),
|
return new BukkitCustomItem(this.id, this.item, this.clientBoundItem, this.itemKey, this.clientBoundItemKey, List.copyOf(this.behaviors),
|
||||||
List.copyOf(this.modifiers), List.copyOf(this.clientBoundModifiers), this.settings, this.events);
|
List.copyOf(this.modifiers), List.copyOf(this.clientBoundModifiers), this.settings, this.events);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.item;
|
|||||||
|
|
||||||
import com.saicone.rtag.item.ItemTagStream;
|
import com.saicone.rtag.item.ItemTagStream;
|
||||||
import net.momirealms.craftengine.bukkit.item.behavior.BucketItemBehavior;
|
import net.momirealms.craftengine.bukkit.item.behavior.BucketItemBehavior;
|
||||||
|
import net.momirealms.craftengine.bukkit.item.behavior.FlintAndSteelItemBehavior;
|
||||||
import net.momirealms.craftengine.bukkit.item.behavior.WaterBucketItemBehavior;
|
import net.momirealms.craftengine.bukkit.item.behavior.WaterBucketItemBehavior;
|
||||||
import net.momirealms.craftengine.bukkit.item.factory.BukkitItemFactory;
|
import net.momirealms.craftengine.bukkit.item.factory.BukkitItemFactory;
|
||||||
import net.momirealms.craftengine.bukkit.item.listener.ArmorEventListener;
|
import net.momirealms.craftengine.bukkit.item.listener.ArmorEventListener;
|
||||||
@@ -12,6 +13,7 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
|
||||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||||
import net.momirealms.craftengine.core.entity.player.Player;
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
@@ -43,6 +45,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
|||||||
static {
|
static {
|
||||||
registerVanillaItemExtraBehavior(WaterBucketItemBehavior.INSTANCE, ItemKeys.WATER_BUCKETS);
|
registerVanillaItemExtraBehavior(WaterBucketItemBehavior.INSTANCE, ItemKeys.WATER_BUCKETS);
|
||||||
registerVanillaItemExtraBehavior(BucketItemBehavior.INSTANCE, ItemKeys.BUCKET);
|
registerVanillaItemExtraBehavior(BucketItemBehavior.INSTANCE, ItemKeys.BUCKET);
|
||||||
|
registerVanillaItemExtraBehavior(FlintAndSteelItemBehavior.INSTANCE, ItemKeys.FLINT_AND_STEEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BukkitItemManager instance;
|
private static BukkitItemManager instance;
|
||||||
@@ -198,9 +201,19 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CustomItem.Builder<ItemStack> createPlatformItemBuilder(Holder<Key> id, Key materialId) {
|
protected CustomItem.Builder<ItemStack> createPlatformItemBuilder(Holder<Key> id, Key materialId, Key clientBoundMaterialId) {
|
||||||
Material material = ResourceConfigUtils.requireNonNullOrThrow(Registry.MATERIAL.get(KeyUtils.toNamespacedKey(materialId)), () -> new LocalizedResourceConfigException("warning.config.item.invalid_material", materialId.toString()));
|
Object item = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, KeyUtils.toResourceLocation(materialId));
|
||||||
return BukkitCustomItem.builder(material).material(materialId).id(id);
|
Object clientBoundItem = materialId == clientBoundMaterialId ? item : FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, KeyUtils.toResourceLocation(clientBoundMaterialId));
|
||||||
|
if (item == null) {
|
||||||
|
throw new LocalizedResourceConfigException("warning.config.item.invalid_material", materialId.toString());
|
||||||
|
}
|
||||||
|
if (clientBoundItem == null) {
|
||||||
|
throw new LocalizedResourceConfigException("warning.config.item.invalid_material", clientBoundMaterialId.toString());
|
||||||
|
}
|
||||||
|
return BukkitCustomItem.builder(item, clientBoundItem)
|
||||||
|
.id(id)
|
||||||
|
.material(materialId)
|
||||||
|
.clientBoundMaterial(clientBoundMaterialId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -214,7 +227,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
|||||||
.orElseGet(() -> ((WritableRegistry<Key>) BuiltInRegistries.OPTIMIZED_ITEM_ID)
|
.orElseGet(() -> ((WritableRegistry<Key>) BuiltInRegistries.OPTIMIZED_ITEM_ID)
|
||||||
.register(new ResourceKey<>(BuiltInRegistries.OPTIMIZED_ITEM_ID.key().location(), id), id));
|
.register(new ResourceKey<>(BuiltInRegistries.OPTIMIZED_ITEM_ID.key().location(), id), id));
|
||||||
Object resourceLocation = KeyUtils.toResourceLocation(id.namespace(), id.value());
|
Object resourceLocation = KeyUtils.toResourceLocation(id.namespace(), id.value());
|
||||||
Object mcHolder = ((Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(MBuiltInRegistries.ITEM, CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.instance$Registries$ITEM, resourceLocation))).get();
|
Object mcHolder = ((Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(MBuiltInRegistries.ITEM, CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.ITEM, resourceLocation))).get();
|
||||||
Set<Object> tags = (Set<Object>) CoreReflections.field$Holder$Reference$tags.get(mcHolder);
|
Set<Object> tags = (Set<Object>) CoreReflections.field$Holder$Reference$tags.get(mcHolder);
|
||||||
for (Object tag : tags) {
|
for (Object tag : tags) {
|
||||||
Key tagId = Key.of(CoreReflections.field$TagKey$location.get(tag).toString());
|
Key tagId = Key.of(CoreReflections.field$TagKey$location.get(tag).toString());
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
|
|||||||
private void setComponentInternal(Object type, DynamicOps ops, Object value) {
|
private void setComponentInternal(Object type, DynamicOps ops, Object value) {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
Object componentType = ensureDataComponentType(type);
|
Object componentType = ensureDataComponentType(type);
|
||||||
|
if (componentType == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Codec codec = FastNMS.INSTANCE.method$DataComponentType$codec(componentType);
|
Codec codec = FastNMS.INSTANCE.method$DataComponentType$codec(componentType);
|
||||||
try {
|
try {
|
||||||
DataResult<Object> result = codec.parse(ops, value);
|
DataResult<Object> result = codec.parse(ops, value);
|
||||||
@@ -162,4 +165,9 @@ public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
|
|||||||
public void count(int amount) {
|
public void count(int amount) {
|
||||||
this.item.setAmount(Math.max(amount, 0));
|
this.item.setAmount(Math.max(amount, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shrink(int amount) {
|
||||||
|
count(count() - amount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,18 +8,9 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
|
|
||||||
public class LegacyItemWrapper implements ItemWrapper<ItemStack> {
|
public class LegacyItemWrapper implements ItemWrapper<ItemStack> {
|
||||||
private final RtagItem rtagItem;
|
private final RtagItem rtagItem;
|
||||||
private int count;
|
|
||||||
|
|
||||||
public LegacyItemWrapper(RtagItem rtagItem, int count) {
|
public LegacyItemWrapper(RtagItem rtagItem) {
|
||||||
this.rtagItem = rtagItem;
|
this.rtagItem = rtagItem;
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getItem() {
|
|
||||||
ItemStack itemStack = this.rtagItem.getItem();
|
|
||||||
itemStack.setAmount(this.count);
|
|
||||||
return itemStack;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setTag(Object value, Object... path) {
|
public boolean setTag(Object value, Object... path) {
|
||||||
@@ -49,12 +40,12 @@ public class LegacyItemWrapper implements ItemWrapper<ItemStack> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int count() {
|
public int count() {
|
||||||
return this.count;
|
return getItem().getAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void count(int amount) {
|
public void count(int amount) {
|
||||||
if (amount < 0) amount = 0;
|
if (amount < 0) amount = 0;
|
||||||
this.count = amount;
|
getItem().setAmount(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getExactTag(Object... path) {
|
public Object getExactTag(Object... path) {
|
||||||
@@ -75,9 +66,12 @@ public class LegacyItemWrapper implements ItemWrapper<ItemStack> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack load() {
|
public ItemStack load() {
|
||||||
ItemStack itemStack = this.rtagItem.load();
|
return this.rtagItem.load();
|
||||||
itemStack.setAmount(Math.max(this.count, 0));
|
}
|
||||||
return itemStack;
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItem() {
|
||||||
|
return this.rtagItem.getItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -87,6 +81,13 @@ public class LegacyItemWrapper implements ItemWrapper<ItemStack> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemWrapper<ItemStack> copyWithCount(int count) {
|
public ItemWrapper<ItemStack> copyWithCount(int count) {
|
||||||
return new LegacyItemWrapper(new RtagItem(this.rtagItem.loadCopy()), count);
|
ItemStack copied = this.rtagItem.loadCopy();
|
||||||
|
copied.setAmount(count);
|
||||||
|
return new LegacyItemWrapper(new RtagItem(copied));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shrink(int amount) {
|
||||||
|
this.count(count() - amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.momirealms.craftengine.bukkit.item;
|
package net.momirealms.craftengine.bukkit.item;
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.core.entity.player.Player;
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
import net.momirealms.craftengine.core.item.CustomItem;
|
import net.momirealms.craftengine.core.item.CustomItem;
|
||||||
import net.momirealms.craftengine.core.item.Item;
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
@@ -25,11 +26,25 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Item<ItemStack>> c2s(Item<ItemStack> wrapped) {
|
public Optional<Item<ItemStack>> c2s(Item<ItemStack> wrapped) {
|
||||||
if (!wrapped.hasTag(NETWORK_ITEM_TAG)) return Optional.empty();
|
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||||
|
boolean hasDifferentMaterial = false;
|
||||||
|
if (optionalCustomItem.isPresent()) {
|
||||||
|
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();
|
||||||
|
if (customItem.item() != FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject())) {
|
||||||
|
wrapped = wrapped.unsafeTransmuteCopy(customItem.item(), wrapped.count());
|
||||||
|
hasDifferentMaterial = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!wrapped.hasTag(NETWORK_ITEM_TAG)) {
|
||||||
|
if (hasDifferentMaterial) {
|
||||||
|
return Optional.of(wrapped);
|
||||||
|
}
|
||||||
|
}
|
||||||
CompoundTag networkData = (CompoundTag) wrapped.getNBTTag(NETWORK_ITEM_TAG);
|
CompoundTag networkData = (CompoundTag) wrapped.getNBTTag(NETWORK_ITEM_TAG);
|
||||||
if (networkData == null) return Optional.empty();
|
if (networkData == null) return Optional.empty();
|
||||||
wrapped.removeTag(NETWORK_ITEM_TAG);
|
wrapped.removeTag(NETWORK_ITEM_TAG);
|
||||||
@@ -46,12 +61,16 @@ public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
|||||||
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||||
if (optionalCustomItem.isEmpty()) {
|
if (optionalCustomItem.isEmpty()) {
|
||||||
if (!Config.interceptItem()) return Optional.empty();
|
if (!Config.interceptItem()) return Optional.empty();
|
||||||
return new OtherItem(wrapped).process();
|
return new OtherItem(wrapped, false).process();
|
||||||
} else {
|
} else {
|
||||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();
|
||||||
|
boolean hasDifferentMaterial = FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject()) != customItem.clientItem();
|
||||||
|
if (hasDifferentMaterial) {
|
||||||
|
wrapped = wrapped.unsafeTransmuteCopy(customItem.clientItem(), wrapped.count());
|
||||||
|
}
|
||||||
if (!customItem.hasClientBoundDataModifier()) {
|
if (!customItem.hasClientBoundDataModifier()) {
|
||||||
if (!Config.interceptItem()) return Optional.empty();
|
if (!Config.interceptItem() && !hasDifferentMaterial) return Optional.empty();
|
||||||
return new OtherItem(wrapped).process();
|
return new OtherItem(wrapped, hasDifferentMaterial).process();
|
||||||
} else {
|
} else {
|
||||||
CompoundTag tag = new CompoundTag();
|
CompoundTag tag = new CompoundTag();
|
||||||
Tag argumentTag = wrapped.getNBTTag(ArgumentModifier.ARGUMENTS_TAG);
|
Tag argumentTag = wrapped.getNBTTag(ArgumentModifier.ARGUMENTS_TAG);
|
||||||
@@ -77,7 +96,12 @@ public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
|||||||
processLore(wrapped, tag::put);
|
processLore(wrapped, tag::put);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tag.isEmpty()) return Optional.empty();
|
if (tag.isEmpty()) {
|
||||||
|
if (hasDifferentMaterial) {
|
||||||
|
return Optional.of(wrapped);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
wrapped.setTag(tag, NETWORK_ITEM_TAG);
|
wrapped.setTag(tag, NETWORK_ITEM_TAG);
|
||||||
return Optional.of(wrapped);
|
return Optional.of(wrapped);
|
||||||
}
|
}
|
||||||
@@ -130,9 +154,11 @@ public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
|||||||
private final Item<ItemStack> item;
|
private final Item<ItemStack> item;
|
||||||
private boolean globalChanged = false;
|
private boolean globalChanged = false;
|
||||||
private CompoundTag networkTag;
|
private CompoundTag networkTag;
|
||||||
|
private final boolean forceReturn;
|
||||||
|
|
||||||
public OtherItem(Item<ItemStack> item) {
|
public OtherItem(Item<ItemStack> item, boolean forceReturn) {
|
||||||
this.item = item;
|
this.item = item;
|
||||||
|
this.forceReturn = forceReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Item<ItemStack>> process() {
|
public Optional<Item<ItemStack>> process() {
|
||||||
@@ -145,6 +171,8 @@ public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
|||||||
if (this.globalChanged) {
|
if (this.globalChanged) {
|
||||||
this.item.setTag(this.networkTag, NETWORK_ITEM_TAG);
|
this.item.setTag(this.networkTag, NETWORK_ITEM_TAG);
|
||||||
return Optional.of(this.item);
|
return Optional.of(this.item);
|
||||||
|
} else if (this.forceReturn) {
|
||||||
|
return Optional.of(this.item);
|
||||||
} else {
|
} else {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.momirealms.craftengine.bukkit.item;
|
package net.momirealms.craftengine.bukkit.item;
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.core.entity.player.Player;
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
import net.momirealms.craftengine.core.item.*;
|
import net.momirealms.craftengine.core.item.*;
|
||||||
import net.momirealms.craftengine.core.item.modifier.ArgumentModifier;
|
import net.momirealms.craftengine.core.item.modifier.ArgumentModifier;
|
||||||
@@ -30,8 +31,22 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
|||||||
public Optional<Item<ItemStack>> c2s(Item<ItemStack> wrapped) {
|
public Optional<Item<ItemStack>> c2s(Item<ItemStack> wrapped) {
|
||||||
Tag customData = wrapped.getNBTComponent(ComponentTypes.CUSTOM_DATA);
|
Tag customData = wrapped.getNBTComponent(ComponentTypes.CUSTOM_DATA);
|
||||||
if (!(customData instanceof CompoundTag compoundTag)) return Optional.empty();
|
if (!(customData instanceof CompoundTag compoundTag)) return Optional.empty();
|
||||||
|
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||||
|
boolean hasDifferentMaterial = false;
|
||||||
|
if (optionalCustomItem.isPresent()) {
|
||||||
|
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();
|
||||||
|
if (customItem.item() != FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject())) {
|
||||||
|
wrapped = wrapped.unsafeTransmuteCopy(customItem.item(), wrapped.count());
|
||||||
|
hasDifferentMaterial = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
CompoundTag networkData = compoundTag.getCompound(NETWORK_ITEM_TAG);
|
CompoundTag networkData = compoundTag.getCompound(NETWORK_ITEM_TAG);
|
||||||
if (networkData == null) return Optional.empty();
|
if (networkData == null) {
|
||||||
|
if (hasDifferentMaterial) {
|
||||||
|
return Optional.of(wrapped);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
compoundTag.remove(NETWORK_ITEM_TAG);
|
compoundTag.remove(NETWORK_ITEM_TAG);
|
||||||
for (Map.Entry<String, Tag> entry : networkData.entrySet()) {
|
for (Map.Entry<String, Tag> entry : networkData.entrySet()) {
|
||||||
if (entry.getValue() instanceof CompoundTag tag) {
|
if (entry.getValue() instanceof CompoundTag tag) {
|
||||||
@@ -48,12 +63,16 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
|||||||
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||||
if (optionalCustomItem.isEmpty()) {
|
if (optionalCustomItem.isEmpty()) {
|
||||||
if (!Config.interceptItem()) return Optional.empty();
|
if (!Config.interceptItem()) return Optional.empty();
|
||||||
return new OtherItem(wrapped).process();
|
return new OtherItem(wrapped, false).process();
|
||||||
} else {
|
} else {
|
||||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();
|
||||||
|
boolean hasDifferentMaterial = FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject()) != customItem.clientItem();
|
||||||
|
if (hasDifferentMaterial) {
|
||||||
|
wrapped = wrapped.unsafeTransmuteCopy(customItem.clientItem(), wrapped.count());
|
||||||
|
}
|
||||||
if (!customItem.hasClientBoundDataModifier()) {
|
if (!customItem.hasClientBoundDataModifier()) {
|
||||||
if (!Config.interceptItem()) return Optional.empty();
|
if (!Config.interceptItem() && !hasDifferentMaterial) return Optional.empty();
|
||||||
return new OtherItem(wrapped).process();
|
return new OtherItem(wrapped, hasDifferentMaterial).process();
|
||||||
} else {
|
} else {
|
||||||
CompoundTag customData = Optional.ofNullable(wrapped.getNBTComponent(ComponentTypes.CUSTOM_DATA)).map(CompoundTag.class::cast).orElse(new CompoundTag());
|
CompoundTag customData = Optional.ofNullable(wrapped.getNBTComponent(ComponentTypes.CUSTOM_DATA)).map(CompoundTag.class::cast).orElse(new CompoundTag());
|
||||||
CompoundTag arguments = customData.getCompound(ArgumentModifier.ARGUMENTS_TAG);
|
CompoundTag arguments = customData.getCompound(ArgumentModifier.ARGUMENTS_TAG);
|
||||||
@@ -86,7 +105,10 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
|||||||
else processLegacyLore(wrapped, () -> tag);
|
else processLegacyLore(wrapped, () -> tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tag.isEmpty()) return Optional.empty();
|
if (tag.isEmpty()) {
|
||||||
|
if (hasDifferentMaterial) return Optional.of(wrapped);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
customData.put(NETWORK_ITEM_TAG, tag);
|
customData.put(NETWORK_ITEM_TAG, tag);
|
||||||
wrapped.setNBTComponent(ComponentTypes.CUSTOM_DATA, customData);
|
wrapped.setNBTComponent(ComponentTypes.CUSTOM_DATA, customData);
|
||||||
return Optional.of(wrapped);
|
return Optional.of(wrapped);
|
||||||
@@ -203,11 +225,13 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
|||||||
|
|
||||||
static class OtherItem {
|
static class OtherItem {
|
||||||
private final Item<ItemStack> item;
|
private final Item<ItemStack> item;
|
||||||
|
private final boolean forceReturn;
|
||||||
private boolean globalChanged = false;
|
private boolean globalChanged = false;
|
||||||
private CompoundTag tag;
|
private CompoundTag tag;
|
||||||
|
|
||||||
public OtherItem(Item<ItemStack> item) {
|
public OtherItem(Item<ItemStack> item, boolean forceReturn) {
|
||||||
this.item = item;
|
this.item = item;
|
||||||
|
this.forceReturn = forceReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Item<ItemStack>> process() {
|
public Optional<Item<ItemStack>> process() {
|
||||||
@@ -231,6 +255,8 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
|||||||
customData.put(NETWORK_ITEM_TAG, getOrCreateTag());
|
customData.put(NETWORK_ITEM_TAG, getOrCreateTag());
|
||||||
this.item.setNBTComponent(ComponentKeys.CUSTOM_DATA, customData);
|
this.item.setNBTComponent(ComponentKeys.CUSTOM_DATA, customData);
|
||||||
return Optional.of(this.item);
|
return Optional.of(this.item);
|
||||||
|
} else if (this.forceReturn) {
|
||||||
|
return Optional.of(this.item);
|
||||||
} else {
|
} else {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ public class BukkitItemBehaviors extends ItemBehaviors {
|
|||||||
public static final Key FURNITURE_ITEM = Key.from("craftengine:furniture_item");
|
public static final Key FURNITURE_ITEM = Key.from("craftengine:furniture_item");
|
||||||
public static final Key WATER_BUCKET_ITEM = Key.from("craftengine:water_bucket_item");
|
public static final Key WATER_BUCKET_ITEM = Key.from("craftengine:water_bucket_item");
|
||||||
public static final Key BUCKET_ITEM = Key.from("craftengine:bucket_item");
|
public static final Key BUCKET_ITEM = Key.from("craftengine:bucket_item");
|
||||||
public static final Key HAT_ITEM = Key.from("craftengine:hat_item");
|
public static final Key FLINT_AND_STEEL_ITEM = Key.from("craftengine:flint_and_steel_item");
|
||||||
|
public static final Key COMPOSTABLE_ITEM = Key.from("craftengine:compostable_item");
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
register(EMPTY, EmptyItemBehavior.FACTORY);
|
register(EMPTY, EmptyItemBehavior.FACTORY);
|
||||||
@@ -19,5 +20,7 @@ public class BukkitItemBehaviors extends ItemBehaviors {
|
|||||||
register(FURNITURE_ITEM, FurnitureItemBehavior.FACTORY);
|
register(FURNITURE_ITEM, FurnitureItemBehavior.FACTORY);
|
||||||
register(WATER_BUCKET_ITEM, WaterBucketItemBehavior.FACTORY);
|
register(WATER_BUCKET_ITEM, WaterBucketItemBehavior.FACTORY);
|
||||||
register(BUCKET_ITEM, BucketItemBehavior.FACTORY);
|
register(BUCKET_ITEM, BucketItemBehavior.FACTORY);
|
||||||
|
register(FLINT_AND_STEEL_ITEM, FlintAndSteelItemBehavior.FACTORY);
|
||||||
|
register(COMPOSTABLE_ITEM, CompostableItemBehavior.FACTORY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.EventUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
|
||||||
|
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||||
|
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||||
|
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||||
|
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||||
|
import net.momirealms.craftengine.core.pack.Pack;
|
||||||
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||||
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
|
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||||
|
import org.bukkit.GameEvent;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.block.data.Levelled;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CompostableItemBehavior extends ItemBehavior {
|
||||||
|
public static final Factory FACTORY = new Factory();
|
||||||
|
private final double chance;
|
||||||
|
|
||||||
|
public CompostableItemBehavior(double chance) {
|
||||||
|
this.chance = chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InteractionResult useOnBlock(UseOnContext context) {
|
||||||
|
BukkitBlockInWorld block = (BukkitBlockInWorld) context.getLevel().getBlockAt(context.getClickedPos());
|
||||||
|
BlockData blockData = block.block().getBlockData();
|
||||||
|
Object blockOwner = BlockStateUtils.getBlockOwner(BlockStateUtils.blockDataToBlockState(blockData));
|
||||||
|
if (blockOwner != MBlocks.COMPOSTER) return InteractionResult.PASS;
|
||||||
|
if (!(blockData instanceof Levelled levelled)) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
int maxLevel = levelled.getMaximumLevel();
|
||||||
|
int currentLevel = levelled.getLevel();
|
||||||
|
if (currentLevel >= maxLevel) return InteractionResult.PASS;
|
||||||
|
boolean willRaise = (currentLevel == 0) && (this.chance > 0) || (RandomUtils.generateRandomDouble(0, 1) < this.chance);
|
||||||
|
|
||||||
|
if (willRaise) {
|
||||||
|
levelled.setLevel(currentLevel + 1);
|
||||||
|
EntityChangeBlockEvent event = new EntityChangeBlockEvent((Entity) context.getPlayer().platformPlayer(), block.block(), levelled);
|
||||||
|
if (EventUtils.fireAndCheckCancel(event)) {
|
||||||
|
return InteractionResult.FAIL;
|
||||||
|
}
|
||||||
|
block.block().setBlockData(levelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.getLevel().levelEvent(WorldEvents.COMPOSTER_COMPOSTS, context.getClickedPos(), willRaise ? 1 : 0);
|
||||||
|
((World) context.getLevel().platformWorld()).sendGameEvent((Entity) context.getPlayer().platformPlayer(), GameEvent.BLOCK_CHANGE, new Vector(block.x() + 0.5, block.y() + 0.5, block.z() + 0.5));
|
||||||
|
if (currentLevel + 1 == 7) {
|
||||||
|
FastNMS.INSTANCE.method$LevelAccessor$scheduleTick(context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), blockOwner, 20);
|
||||||
|
}
|
||||||
|
if (!context.getPlayer().canInstabuild()) {
|
||||||
|
context.getItem().shrink(1);
|
||||||
|
}
|
||||||
|
context.getPlayer().swingHand(context.getHand());
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Factory implements ItemBehaviorFactory {
|
||||||
|
@Override
|
||||||
|
public ItemBehavior create(Pack pack, Path path, Key key, Map<String, Object> arguments) {
|
||||||
|
double chance = ResourceConfigUtils.getAsDouble(arguments.getOrDefault("chance", 0.55), "chance");
|
||||||
|
return new CompostableItemBehavior(chance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.InteractUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
|
||||||
|
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||||
|
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||||
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
|
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||||
|
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||||
|
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||||
|
import net.momirealms.craftengine.core.pack.Pack;
|
||||||
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
|
import net.momirealms.craftengine.core.sound.SoundSource;
|
||||||
|
import net.momirealms.craftengine.core.util.Direction;
|
||||||
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||||
|
import net.momirealms.craftengine.core.world.BlockPos;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class FlintAndSteelItemBehavior extends ItemBehavior {
|
||||||
|
public static final FlintAndSteelItemBehavior INSTANCE = new FlintAndSteelItemBehavior();
|
||||||
|
public static final Factory FACTORY = new Factory();
|
||||||
|
private static final Key FLINT_SOUND = Key.of("item.flintandsteel.use");
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public InteractionResult useOnBlock(UseOnContext context) {
|
||||||
|
BlockPos clickedPos = context.getClickedPos();
|
||||||
|
BukkitBlockInWorld clicked = (BukkitBlockInWorld) context.getLevel().getBlockAt(clickedPos);
|
||||||
|
Block block = clicked.block();
|
||||||
|
BlockPos firePos = clickedPos.relative(context.getClickedFace());
|
||||||
|
Direction direction = context.getHorizontalDirection();
|
||||||
|
|
||||||
|
// 最基础的判断能不能着火,不能着火都是扯蛋
|
||||||
|
try {
|
||||||
|
if (!(boolean) CoreReflections.method$BaseFireBlock$canBePlacedAt.invoke(null, context.getLevel().serverWorld(), LocationUtils.toBlockPos(firePos), DirectionUtils.toNMSDirection(direction))) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
CraftEngine.instance().logger().warn("Failed to call BaseFireBlock$canBePlacedAt", e);
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断点击的方块是否可燃
|
||||||
|
BlockData clickedBlockData = block.getBlockData();
|
||||||
|
Object clickedBlockState = BlockStateUtils.blockDataToBlockState(clickedBlockData);
|
||||||
|
boolean isClickedBlockBurnable;
|
||||||
|
try {
|
||||||
|
isClickedBlockBurnable = BlockStateUtils.isBurnable(clickedBlockState) ||
|
||||||
|
(context.getClickedFace() == Direction.UP && (boolean) CoreReflections.method$BlockStateBase$isFaceSturdy.invoke(
|
||||||
|
clickedBlockState, context.getLevel().serverWorld(), LocationUtils.toBlockPos(clickedPos), CoreReflections.instance$Direction$UP, CoreReflections.instance$SupportType$FULL));
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
CraftEngine.instance().logger().warn("Failed to call method$BlockStateBase$isFaceSturdy", e);
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
net.momirealms.craftengine.core.entity.player.Player player = context.getPlayer();
|
||||||
|
// 点击对象直接可燃,则忽略
|
||||||
|
if (isClickedBlockBurnable) {
|
||||||
|
int stateId = BlockStateUtils.blockStateToId(clickedBlockState);
|
||||||
|
if (BlockStateUtils.isVanillaBlock(stateId)) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
} else {
|
||||||
|
// 点击对象为自定义方块
|
||||||
|
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
|
||||||
|
// 原版外观也可燃
|
||||||
|
if (BlockStateUtils.isBurnable(immutableBlockState.vanillaBlockState().handle())) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
BlockData vanillaBlockState = BlockStateUtils.fromBlockData(immutableBlockState.vanillaBlockState().handle());
|
||||||
|
// 点击的是方块上面,则只需要判断shift和可交互
|
||||||
|
if (direction == Direction.UP) {
|
||||||
|
// 客户端层面必须可交互
|
||||||
|
if (!InteractUtils.isInteractable((Player) player.platformPlayer(), vanillaBlockState,
|
||||||
|
context.getHitResult(), (Item<ItemStack>) context.getItem())) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
// 且没有shift
|
||||||
|
if (!player.isSecondaryUseActive()) {
|
||||||
|
player.playSound(FLINT_SOUND, firePos, SoundSource.BLOCK, 1f, RandomUtils.generateRandomFloat(0.8f, 1.2f));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 玩家觉得自定义方块不可燃,且点击了侧面,那么就要判断火源下方的方块是否可燃,如果不可燃,则补发声音
|
||||||
|
BlockPos belowFirePos = firePos.relative(Direction.DOWN);
|
||||||
|
BukkitBlockInWorld belowFireBlock = (BukkitBlockInWorld) context.getLevel().getBlockAt(belowFirePos);
|
||||||
|
boolean belowCanBurn;
|
||||||
|
try {
|
||||||
|
Block belowBlock = belowFireBlock.block();
|
||||||
|
belowCanBurn = BlockStateUtils.isBurnable(BlockStateUtils.blockDataToBlockState(belowBlock.getBlockData())) ||
|
||||||
|
(boolean) CoreReflections.method$BlockStateBase$isFaceSturdy.invoke(
|
||||||
|
BlockStateUtils.blockDataToBlockState(belowFireBlock.block().getBlockData()), context.getLevel().serverWorld(), LocationUtils.toBlockPos(belowFirePos), CoreReflections.instance$Direction$UP, CoreReflections.instance$SupportType$FULL);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
CraftEngine.instance().logger().warn("Failed to call method$BlockStateBase$isFaceSturdy", e);
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 客户端觉得这玩意可交互,就会忽略声音
|
||||||
|
if (InteractUtils.isInteractable((Player) player.platformPlayer(), vanillaBlockState, context.getHitResult(), (Item<ItemStack>) context.getItem())) {
|
||||||
|
// 如果按住了shift,则代表尝试对侧面方块点火
|
||||||
|
if (player.isSecondaryUseActive()) {
|
||||||
|
// 如果底部不能燃烧,则燃烧点位为侧面,需要补发
|
||||||
|
if (!belowCanBurn) {
|
||||||
|
player.playSound(FLINT_SOUND, firePos, SoundSource.BLOCK, 1f, RandomUtils.generateRandomFloat(0.8f, 1.2f));
|
||||||
|
player.swingHand(context.getHand());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
player.playSound(FLINT_SOUND, firePos, SoundSource.BLOCK, 1f, RandomUtils.generateRandomFloat(0.8f, 1.2f));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果底部方块不可燃烧才补发
|
||||||
|
if (!belowCanBurn) {
|
||||||
|
player.playSound(FLINT_SOUND, firePos, SoundSource.BLOCK, 1f, RandomUtils.generateRandomFloat(0.8f, 1.2f));
|
||||||
|
player.swingHand(context.getHand());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果点击的方块不可燃烧,但是服务端却认为可以放置火源,则可燃烧的方块一定位于火源的六个方向之一。
|
||||||
|
Direction relativeDirection = direction.opposite();
|
||||||
|
for (Direction dir : Direction.values()) {
|
||||||
|
if (dir == relativeDirection) continue;
|
||||||
|
BlockPos relPos = firePos.relative(dir);
|
||||||
|
BukkitBlockInWorld nearByBlock = (BukkitBlockInWorld) context.getLevel().getBlockAt(relPos);
|
||||||
|
BlockData nearbyBlockData = nearByBlock.block().getBlockData();
|
||||||
|
Object nearbyBlockState = BlockStateUtils.blockDataToBlockState(nearbyBlockData);
|
||||||
|
int stateID = BlockStateUtils.blockStateToId(nearbyBlockState);
|
||||||
|
if (BlockStateUtils.isVanillaBlock(stateID)) {
|
||||||
|
if (BlockStateUtils.isBurnable(nearbyBlockState)) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (dir == Direction.DOWN && (boolean) CoreReflections.method$BlockStateBase$isFaceSturdy.invoke(
|
||||||
|
nearbyBlockState, context.getLevel().serverWorld(), LocationUtils.toBlockPos(relPos), CoreReflections.instance$Direction$UP, CoreReflections.instance$SupportType$FULL)) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
CraftEngine.instance().logger().warn("Failed to call method$BlockStateBase$isFaceSturdy", e);
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player.playSound(FLINT_SOUND, firePos, SoundSource.BLOCK, 1f, RandomUtils.generateRandomFloat(0.8f, 1.2f));
|
||||||
|
player.swingHand(context.getHand());
|
||||||
|
}
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Factory implements ItemBehaviorFactory {
|
||||||
|
@Override
|
||||||
|
public ItemBehavior create(Pack pack, Path path, Key id, Map<String, Object> arguments) {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,12 +2,13 @@ package net.momirealms.craftengine.bukkit.item.factory;
|
|||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.saicone.rtag.item.ItemTagStream;
|
import com.saicone.rtag.item.ItemTagStream;
|
||||||
|
import net.momirealms.craftengine.bukkit.item.ComponentItemWrapper;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
import net.momirealms.craftengine.bukkit.util.ItemTags;
|
import net.momirealms.craftengine.bukkit.util.ItemTags;
|
||||||
import net.momirealms.craftengine.core.item.EquipmentData;
|
|
||||||
import net.momirealms.craftengine.core.item.ItemFactory;
|
import net.momirealms.craftengine.core.item.ItemFactory;
|
||||||
import net.momirealms.craftengine.core.item.ItemWrapper;
|
import net.momirealms.craftengine.core.item.ItemWrapper;
|
||||||
import net.momirealms.craftengine.core.item.JukeboxPlayable;
|
import net.momirealms.craftengine.core.item.JukeboxPlayable;
|
||||||
|
import net.momirealms.craftengine.core.item.setting.EquipmentData;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.sparrow.nbt.Tag;
|
import net.momirealms.sparrow.nbt.Tag;
|
||||||
|
|||||||
@@ -4,11 +4,16 @@ import com.google.gson.JsonElement;
|
|||||||
import net.momirealms.craftengine.bukkit.item.ComponentItemWrapper;
|
import net.momirealms.craftengine.bukkit.item.ComponentItemWrapper;
|
||||||
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
|
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
|
||||||
import net.momirealms.craftengine.bukkit.util.EnchantmentUtils;
|
import net.momirealms.craftengine.bukkit.util.EnchantmentUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||||
import net.momirealms.craftengine.core.item.Enchantment;
|
import net.momirealms.craftengine.core.item.Enchantment;
|
||||||
import net.momirealms.craftengine.core.item.Trim;
|
import net.momirealms.craftengine.core.item.Trim;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
import net.momirealms.sparrow.nbt.Tag;
|
import net.momirealms.sparrow.nbt.Tag;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
@@ -38,29 +43,136 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
|||||||
return new ComponentItemWrapper(item);
|
return new ComponentItemWrapper(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
protected Object getJavaTag(ComponentItemWrapper item, Object... path) {
|
protected Object getJavaTag(ComponentItemWrapper item, Object... path) {
|
||||||
throw new UnsupportedOperationException("This feature is not available on 1.20.5+");
|
Map<String, Object> rootMap = (Map<String, Object>) item.getJavaComponent(ComponentTypes.CUSTOM_DATA).orElse(null);
|
||||||
|
if (rootMap == null) return null;
|
||||||
|
Object currentObj = rootMap;
|
||||||
|
for (int i = 0; i < path.length; i++) {
|
||||||
|
Object pathSegment = path[i];
|
||||||
|
if (pathSegment == null) return null;
|
||||||
|
String key = pathSegment.toString();
|
||||||
|
currentObj = ((Map<String, Object>) currentObj).get(key);
|
||||||
|
if (currentObj == null) return null;
|
||||||
|
if (i == path.length - 1) {
|
||||||
|
return currentObj;
|
||||||
|
}
|
||||||
|
if (!(currentObj instanceof Map)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Tag getNBTTag(ComponentItemWrapper item, Object... path) {
|
protected Tag getNBTTag(ComponentItemWrapper item, Object... path) {
|
||||||
throw new UnsupportedOperationException("This feature is not available on 1.20.5+");
|
CompoundTag rootTag = (CompoundTag) item.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA).orElse(null);
|
||||||
|
if (rootTag == null) return null;
|
||||||
|
Tag currentTag = rootTag;
|
||||||
|
for (int i = 0; i < path.length; i++) {
|
||||||
|
Object pathSegment = path[i];
|
||||||
|
if (pathSegment == null) return null;
|
||||||
|
CompoundTag t = (CompoundTag) currentTag;
|
||||||
|
String key = pathSegment.toString();
|
||||||
|
currentTag = t.get(key);
|
||||||
|
if (currentTag == null) return null;
|
||||||
|
if (i == path.length - 1) {
|
||||||
|
return currentTag;
|
||||||
|
}
|
||||||
|
if (!(currentTag instanceof CompoundTag)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setTag(ComponentItemWrapper item, Object value, Object... path) {
|
protected void setTag(ComponentItemWrapper item, Object value, Object... path) {
|
||||||
throw new UnsupportedOperationException("This feature is not available on 1.20.5+");
|
Tag valueTag;
|
||||||
|
if (value instanceof Tag tag) {
|
||||||
|
valueTag = tag;
|
||||||
|
} else if (value instanceof JsonElement je) {
|
||||||
|
valueTag = MRegistryOps.JSON.convertTo(MRegistryOps.SPARROW_NBT, je);
|
||||||
|
} else if (CoreReflections.clazz$Tag.isInstance(value)) {
|
||||||
|
valueTag = MRegistryOps.NBT.convertTo(MRegistryOps.SPARROW_NBT, value);
|
||||||
|
} else {
|
||||||
|
assert MRegistryOps.JAVA != null;
|
||||||
|
valueTag = MRegistryOps.JAVA.convertTo(MRegistryOps.SPARROW_NBT, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundTag rootTag = (CompoundTag) item.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA).orElse(new CompoundTag());
|
||||||
|
|
||||||
|
if (path == null || path.length == 0) {
|
||||||
|
if (valueTag instanceof CompoundTag) {
|
||||||
|
rootTag = (CompoundTag) valueTag;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Cannot set non-CompoundTag as root without path");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CompoundTag currentTag = rootTag;
|
||||||
|
for (int i = 0; i < path.length - 1; i++) {
|
||||||
|
Object pathSegment = path[i];
|
||||||
|
if (pathSegment == null) throw new NullPointerException("Path segment cannot be null");
|
||||||
|
|
||||||
|
String key = pathSegment.toString();
|
||||||
|
Tag nextTag = currentTag.get(key);
|
||||||
|
|
||||||
|
if (!(nextTag instanceof CompoundTag)) {
|
||||||
|
nextTag = new CompoundTag();
|
||||||
|
currentTag.put(key, nextTag);
|
||||||
|
}
|
||||||
|
currentTag = (CompoundTag) nextTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
String finalKey = path[path.length - 1].toString();
|
||||||
|
currentTag.put(finalKey, valueTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
item.setSparrowNBTComponent(ComponentTypes.CUSTOM_DATA, rootTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasTag(ComponentItemWrapper item, Object... path) {
|
protected boolean hasTag(ComponentItemWrapper item, Object... path) {
|
||||||
throw new UnsupportedOperationException("This feature is not available on 1.20.5+");
|
return getNBTTag(item, path) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean removeTag(ComponentItemWrapper item, Object... path) {
|
protected boolean removeTag(ComponentItemWrapper item, Object... path) {
|
||||||
throw new UnsupportedOperationException("This feature is not available on 1.20.5+");
|
CompoundTag rootTag = (CompoundTag) item.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA).orElse(null);
|
||||||
|
if (rootTag == null || path == null || path.length == 0) return false;
|
||||||
|
|
||||||
|
if (path.length == 1) {
|
||||||
|
String key = path[0].toString();
|
||||||
|
if (rootTag.containsKey(key)) {
|
||||||
|
rootTag.remove(key);
|
||||||
|
item.setSparrowNBTComponent(ComponentTypes.CUSTOM_DATA, rootTag);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundTag parentTag = rootTag;
|
||||||
|
for (int i = 0; i < path.length - 1; i++) {
|
||||||
|
Object pathSegment = path[i];
|
||||||
|
if (pathSegment == null) return false;
|
||||||
|
|
||||||
|
String key = pathSegment.toString();
|
||||||
|
Tag childTag = parentTag.get(key);
|
||||||
|
|
||||||
|
if (!(childTag instanceof CompoundTag)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
parentTag = (CompoundTag) childTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
String finalKey = path[path.length - 1].toString();
|
||||||
|
if (parentTag.containsKey(finalKey)) {
|
||||||
|
parentTag.remove(finalKey);
|
||||||
|
item.setSparrowNBTComponent(ComponentTypes.CUSTOM_DATA, rootTag);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -397,9 +509,9 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
|||||||
protected ComponentItemWrapper mergeCopy(ComponentItemWrapper item1, ComponentItemWrapper item2) {
|
protected ComponentItemWrapper mergeCopy(ComponentItemWrapper item1, ComponentItemWrapper item2) {
|
||||||
Object itemStack1 = item1.getLiteralObject();
|
Object itemStack1 = item1.getLiteralObject();
|
||||||
Object itemStack2 = item2.getLiteralObject();
|
Object itemStack2 = item2.getLiteralObject();
|
||||||
Object itemStack3 = FastNMS.INSTANCE.method$ItemStack$transmuteCopy(itemStack1, itemStack2);
|
Object itemStack3 = FastNMS.INSTANCE.method$ItemStack$transmuteCopy(itemStack1, FastNMS.INSTANCE.method$ItemStack$getItem(itemStack2), item2.count());
|
||||||
FastNMS.INSTANCE.method$ItemStack$applyComponents(itemStack3, FastNMS.INSTANCE.method$ItemStack$getComponentsPatch(itemStack2));
|
FastNMS.INSTANCE.method$ItemStack$applyComponents(itemStack3, FastNMS.INSTANCE.method$ItemStack$getComponentsPatch(itemStack2));
|
||||||
return new ComponentItemWrapper(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack3), item2.count());
|
return new ComponentItemWrapper(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack3));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -409,7 +521,21 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
|||||||
try {
|
try {
|
||||||
FastNMS.INSTANCE.method$ItemStack$applyComponents(itemStack1, FastNMS.INSTANCE.method$ItemStack$getComponentsPatch(itemStack2));
|
FastNMS.INSTANCE.method$ItemStack$applyComponents(itemStack1, FastNMS.INSTANCE.method$ItemStack$getComponentsPatch(itemStack2));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
plugin.logger().warn("Failed to merge item", e);
|
this.plugin.logger().warn("Failed to merge item", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ComponentItemWrapper transmuteCopy(ComponentItemWrapper item, Key newItem, int amount) {
|
||||||
|
Object itemStack1 = item.getLiteralObject();
|
||||||
|
Object itemStack2 = FastNMS.INSTANCE.method$ItemStack$transmuteCopy(itemStack1, FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, KeyUtils.toResourceLocation(newItem)), amount);
|
||||||
|
return new ComponentItemWrapper(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ComponentItemWrapper unsafeTransmuteCopy(ComponentItemWrapper item, Object newItem, int amount) {
|
||||||
|
Object itemStack1 = item.getLiteralObject();
|
||||||
|
Object itemStack2 = FastNMS.INSTANCE.method$ItemStack$transmuteCopy(itemStack1, newItem, amount);
|
||||||
|
return new ComponentItemWrapper(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ package net.momirealms.craftengine.bukkit.item.factory;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.bukkit.item.ComponentItemWrapper;
|
import net.momirealms.craftengine.bukkit.item.ComponentItemWrapper;
|
||||||
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
|
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
|
||||||
import net.momirealms.craftengine.core.item.EquipmentData;
|
import net.momirealms.craftengine.core.item.setting.EquipmentData;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import com.saicone.rtag.tag.TagBase;
|
|||||||
import com.saicone.rtag.tag.TagCompound;
|
import com.saicone.rtag.tag.TagCompound;
|
||||||
import com.saicone.rtag.tag.TagList;
|
import com.saicone.rtag.tag.TagList;
|
||||||
import net.momirealms.craftengine.bukkit.item.LegacyItemWrapper;
|
import net.momirealms.craftengine.bukkit.item.LegacyItemWrapper;
|
||||||
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||||
import net.momirealms.craftengine.core.item.Enchantment;
|
import net.momirealms.craftengine.core.item.Enchantment;
|
||||||
import net.momirealms.craftengine.core.item.Trim;
|
import net.momirealms.craftengine.core.item.Trim;
|
||||||
import net.momirealms.craftengine.core.item.modifier.IdModifier;
|
import net.momirealms.craftengine.core.item.modifier.IdModifier;
|
||||||
@@ -29,7 +32,7 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected LegacyItemWrapper wrapInternal(ItemStack item) {
|
protected LegacyItemWrapper wrapInternal(ItemStack item) {
|
||||||
return new LegacyItemWrapper(new RtagItem(item), item.getAmount());
|
return new LegacyItemWrapper(new RtagItem(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -305,18 +308,32 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
|
|||||||
@Override
|
@Override
|
||||||
protected LegacyItemWrapper mergeCopy(LegacyItemWrapper item1, LegacyItemWrapper item2) {
|
protected LegacyItemWrapper mergeCopy(LegacyItemWrapper item1, LegacyItemWrapper item2) {
|
||||||
Object itemStack = ItemObject.copy(item2.getLiteralObject());
|
Object itemStack = ItemObject.copy(item2.getLiteralObject());
|
||||||
ItemObject.setCustomDataTag(itemStack, TagCompound.clone(ItemObject.getCustomDataTag(item1.getLiteralObject())));
|
FastNMS.INSTANCE.method$ItemStack$setTag(itemStack, TagCompound.clone(FastNMS.INSTANCE.field$ItemStack$getOrCreateTag(item1.getLiteralObject())));
|
||||||
// one more step than vanilla
|
// one more step than vanilla
|
||||||
TagCompound.merge(ItemObject.getCustomDataTag(itemStack), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true);
|
TagCompound.merge(FastNMS.INSTANCE.field$ItemStack$getOrCreateTag(itemStack), FastNMS.INSTANCE.field$ItemStack$getOrCreateTag(item2.getLiteralObject()), true, true);
|
||||||
return new LegacyItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack)), item2.count());
|
return new LegacyItemWrapper(new RtagItem(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void merge(LegacyItemWrapper item1, LegacyItemWrapper item2) {
|
protected void merge(LegacyItemWrapper item1, LegacyItemWrapper item2) {
|
||||||
// load previous changes on nms items
|
// load previous changes on nms items
|
||||||
item1.load();
|
item1.load();
|
||||||
TagCompound.merge(ItemObject.getCustomDataTag(item1.getLiteralObject()), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true);
|
TagCompound.merge(FastNMS.INSTANCE.field$ItemStack$getOrCreateTag(item1.getLiteralObject()), FastNMS.INSTANCE.field$ItemStack$getOrCreateTag(item2.getLiteralObject()), true, true);
|
||||||
// update wrapped item
|
// update wrapped item
|
||||||
item1.update();
|
item1.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LegacyItemWrapper transmuteCopy(LegacyItemWrapper item, Key newItem, int amount) {
|
||||||
|
Object newItemStack = FastNMS.INSTANCE.constructor$ItemStack(FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, KeyUtils.toResourceLocation(newItem)), amount);
|
||||||
|
FastNMS.INSTANCE.method$ItemStack$setTag(newItemStack, TagCompound.clone(FastNMS.INSTANCE.field$ItemStack$getOrCreateTag(item.getLiteralObject())));
|
||||||
|
return new LegacyItemWrapper(new RtagItem(ItemObject.asCraftMirror(newItemStack)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LegacyItemWrapper unsafeTransmuteCopy(LegacyItemWrapper item, Object newItem, int amount) {
|
||||||
|
Object newItemStack = FastNMS.INSTANCE.constructor$ItemStack(newItem, amount);
|
||||||
|
FastNMS.INSTANCE.method$ItemStack$setTag(newItemStack, TagCompound.clone(FastNMS.INSTANCE.field$ItemStack$getOrCreateTag(item.getLiteralObject())));
|
||||||
|
return new LegacyItemWrapper(new RtagItem(ItemObject.asCraftMirror(newItemStack)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ public class DebugStickListener implements Listener {
|
|||||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true);
|
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true);
|
||||||
player.sendPacket(systemChatPacket, false);
|
player.sendPacket(systemChatPacket, false);
|
||||||
} else {
|
} else {
|
||||||
LegacyItemWrapper wrapped = new LegacyItemWrapper(new RtagItem(itemInHand), itemInHand.getAmount());
|
LegacyItemWrapper wrapped = new LegacyItemWrapper(new RtagItem(itemInHand));
|
||||||
Object storedData = wrapped.getJavaTag("craftengine:debug_stick_state");
|
Object storedData = wrapped.getJavaTag("craftengine:debug_stick_state");
|
||||||
if (storedData == null) storedData = new HashMap<>();
|
if (storedData == null) storedData = new HashMap<>();
|
||||||
if (storedData instanceof Map<?,?> map) {
|
if (storedData instanceof Map<?,?> map) {
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ import net.momirealms.craftengine.core.item.CustomItem;
|
|||||||
import net.momirealms.craftengine.core.item.Item;
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||||
|
import net.momirealms.craftengine.core.item.setting.FoodData;
|
||||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||||
import net.momirealms.craftengine.core.util.Cancellable;
|
import net.momirealms.craftengine.core.util.*;
|
||||||
import net.momirealms.craftengine.core.util.Direction;
|
|
||||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||||
import net.momirealms.craftengine.core.world.BlockPos;
|
import net.momirealms.craftengine.core.world.BlockPos;
|
||||||
import net.momirealms.craftengine.core.world.Vec3d;
|
import net.momirealms.craftengine.core.world.Vec3d;
|
||||||
@@ -28,11 +28,16 @@ import org.bukkit.GameMode;
|
|||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.BlockIgniteEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
|
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||||
import org.bukkit.inventory.EquipmentSlot;
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
@@ -49,6 +54,28 @@ public class ItemEventListener implements Listener {
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||||
|
public void onInteractEntity(PlayerInteractEntityEvent event) {
|
||||||
|
BukkitServerPlayer serverPlayer = this.plugin.adapt(event.getPlayer());
|
||||||
|
if (serverPlayer == null) return;
|
||||||
|
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||||
|
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(hand);
|
||||||
|
|
||||||
|
if (itemInHand == null) return;
|
||||||
|
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
||||||
|
if (optionalCustomItem.isEmpty()) return;
|
||||||
|
|
||||||
|
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
|
||||||
|
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||||
|
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
|
||||||
|
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||||
|
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(event.getRightClicked().getLocation()))
|
||||||
|
.withParameter(DirectContextParameters.HAND, hand)
|
||||||
|
);
|
||||||
|
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||||
|
customItem.execute(context, EventTrigger.RIGHT_CLICK);
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||||
public void onInteractBlock(PlayerInteractEvent event) {
|
public void onInteractBlock(PlayerInteractEvent event) {
|
||||||
Action action = event.getAction();
|
Action action = event.getAction();
|
||||||
@@ -62,6 +89,7 @@ public class ItemEventListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||||
|
if (serverPlayer == null) return;
|
||||||
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||||
// 如果本tick内主手已被处理,则不处理副手
|
// 如果本tick内主手已被处理,则不处理副手
|
||||||
// 这是因为客户端可能会同时发主副手交互包,但实际上只能处理其中一个
|
// 这是因为客户端可能会同时发主副手交互包,但实际上只能处理其中一个
|
||||||
@@ -318,18 +346,47 @@ public class ItemEventListener implements Listener {
|
|||||||
if (optionalCustomItem.isEmpty()) {
|
if (optionalCustomItem.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Cancellable dummy = Cancellable.dummy();
|
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
|
||||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||||
PlayerOptionalContext context = PlayerOptionalContext.of(this.plugin.adapt(event.getPlayer()), ContextHolder.builder()
|
PlayerOptionalContext context = PlayerOptionalContext.of(this.plugin.adapt(event.getPlayer()), ContextHolder.builder()
|
||||||
.withParameter(DirectContextParameters.ITEM_IN_HAND, wrapped)
|
.withParameter(DirectContextParameters.ITEM_IN_HAND, wrapped)
|
||||||
.withParameter(DirectContextParameters.EVENT, dummy)
|
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||||
.withParameter(DirectContextParameters.HAND, event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND)
|
.withParameter(DirectContextParameters.HAND, event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND)
|
||||||
);
|
);
|
||||||
customItem.execute(context, EventTrigger.CONSUME);
|
customItem.execute(context, EventTrigger.CONSUME);
|
||||||
if (dummy.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
event.setCancelled(true);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (event.getPlayer().getGameMode() != GameMode.CREATIVE) {
|
||||||
|
Key replacement = customItem.settings().consumeReplacement();
|
||||||
|
if (replacement == null) {
|
||||||
|
event.setReplacement(null);
|
||||||
|
} else {
|
||||||
|
ItemStack replacementItem = this.plugin.itemManager().buildItemStack(replacement, this.plugin.adapt(event.getPlayer()));
|
||||||
|
event.setReplacement(replacementItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
|
||||||
|
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
||||||
|
if (VersionHelper.isOrAbove1_20_5()) return;
|
||||||
|
if (!(event.getEntity() instanceof Player player)) return;
|
||||||
|
ItemStack consumedItem = event.getItem();
|
||||||
|
if (ItemUtils.isEmpty(consumedItem)) return;
|
||||||
|
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(consumedItem);
|
||||||
|
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||||
|
if (optionalCustomItem.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||||
|
FoodData foodData = customItem.settings().foodData();
|
||||||
|
if (foodData == null) return;
|
||||||
|
event.setCancelled(true);
|
||||||
|
int oldFoodLevel = player.getFoodLevel();
|
||||||
|
if (foodData.nutrition() != 0) player.setFoodLevel(MCUtils.clamp(oldFoodLevel + foodData.nutrition(), 0, 20));
|
||||||
|
float oldSaturation = player.getSaturation();
|
||||||
|
if (foodData.saturation() != 0) player.setSaturation(MCUtils.clamp(oldSaturation, 0, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean cancelEventIfHasInteraction(PlayerInteractEvent event, BukkitServerPlayer player, InteractionHand hand) {
|
private boolean cancelEventIfHasInteraction(PlayerInteractEvent event, BukkitServerPlayer player, InteractionHand hand) {
|
||||||
@@ -344,4 +401,17 @@ public class ItemEventListener implements Listener {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
|
public void onEntityDamage(EntityDamageEvent event) {
|
||||||
|
if (event.getEntityType() == EntityType.ITEM && event.getEntity() instanceof org.bukkit.entity.Item item) {
|
||||||
|
Optional.ofNullable(this.plugin.itemManager().wrap(item.getItemStack()))
|
||||||
|
.flatMap(Item::getCustomItem)
|
||||||
|
.ifPresent(it -> {
|
||||||
|
if (it.settings().invulnerable().contains(DamageCauseUtils.fromBukkit(event.getCause()))) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||||
import net.momirealms.craftengine.bukkit.util.MaterialUtils;
|
import net.momirealms.craftengine.bukkit.util.MaterialUtils;
|
||||||
import net.momirealms.craftengine.bukkit.util.RecipeUtils;
|
import net.momirealms.craftengine.bukkit.util.RecipeUtils;
|
||||||
@@ -45,9 +46,9 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
// 将自定义配方转为“广义”配方,接受更加宽容的输入
|
// 将自定义配方转为“广义”配方,接受更加宽容的输入
|
||||||
// 部分过程借助bukkit完成,部分直接通过nms方法注册
|
// 部分过程借助bukkit完成,部分直接通过nms方法注册
|
||||||
private static final Map<Key, BukkitRecipeConvertor<? extends Recipe<ItemStack>>> MIXED_RECIPE_CONVERTORS = new HashMap<>();
|
private static final Map<Key, BukkitRecipeConvertor<? extends Recipe<ItemStack>>> MIXED_RECIPE_CONVERTORS = new HashMap<>();
|
||||||
private static Object nmsRecipeManager;
|
|
||||||
private static final List<Object> injectedIngredients = new ArrayList<>();
|
private static final List<Object> injectedIngredients = new ArrayList<>();
|
||||||
private static final IdentityHashMap<Recipe<ItemStack>, Object> recipeToMcRecipeHolder = new IdentityHashMap<>();
|
private static final IdentityHashMap<Recipe<ItemStack>, Object> CE_RECIPE_2_NMS_HOLDER = new IdentityHashMap<>();
|
||||||
|
private static Object nmsRecipeManager;
|
||||||
|
|
||||||
private static void registerNMSSmithingRecipe(Object recipe) {
|
private static void registerNMSSmithingRecipe(Object recipe) {
|
||||||
try {
|
try {
|
||||||
@@ -265,7 +266,8 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Object nmsRecipeHolderByRecipe(Recipe<ItemStack> recipe) {
|
public Object nmsRecipeHolderByRecipe(Recipe<ItemStack> recipe) {
|
||||||
return recipeToMcRecipeHolder.get(recipe);
|
if (super.isReloading) return null;
|
||||||
|
return CE_RECIPE_2_NMS_HOLDER.get(recipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object nmsRecipeManager() {
|
public static Object nmsRecipeManager() {
|
||||||
@@ -287,6 +289,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load() {
|
||||||
if (!Config.enableRecipeSystem()) return;
|
if (!Config.enableRecipeSystem()) return;
|
||||||
|
super.isReloading = true;
|
||||||
if (VersionHelper.isOrAbove1_21_2()) {
|
if (VersionHelper.isOrAbove1_21_2()) {
|
||||||
try {
|
try {
|
||||||
this.stolenFeatureFlagSet = CoreReflections.field$RecipeManager$featureflagset.get(nmsRecipeManager);
|
this.stolenFeatureFlagSet = CoreReflections.field$RecipeManager$featureflagset.get(nmsRecipeManager);
|
||||||
@@ -308,7 +311,6 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
this.plugin.logger().warn("Failed to unregister recipes", e);
|
this.plugin.logger().warn("Failed to unregister recipes", e);
|
||||||
}
|
}
|
||||||
recipeToMcRecipeHolder.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -320,6 +322,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
unload();
|
unload();
|
||||||
|
CE_RECIPE_2_NMS_HOLDER.clear();
|
||||||
HandlerList.unregisterAll(this.recipeEventListener);
|
HandlerList.unregisterAll(this.recipeEventListener);
|
||||||
if (this.crafterEventListener != null) {
|
if (this.crafterEventListener != null) {
|
||||||
HandlerList.unregisterAll(this.crafterEventListener);
|
HandlerList.unregisterAll(this.crafterEventListener);
|
||||||
@@ -473,6 +476,15 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
|
|
||||||
// clear cache
|
// clear cache
|
||||||
injectedIngredients.clear();
|
injectedIngredients.clear();
|
||||||
|
|
||||||
|
CE_RECIPE_2_NMS_HOLDER.clear();
|
||||||
|
// create mappings
|
||||||
|
for (Map.Entry<Key, Recipe<ItemStack>> entry : this.byId.entrySet()) {
|
||||||
|
Optional<Object> nmsRecipe = getOptionalNMSRecipe(entry.getKey());
|
||||||
|
nmsRecipe.ifPresent(o -> CE_RECIPE_2_NMS_HOLDER.put(entry.getValue(), o));
|
||||||
|
}
|
||||||
|
|
||||||
|
super.isReloading = false;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
this.plugin.logger().warn("Failed to run delayed recipe tasks", e);
|
this.plugin.logger().warn("Failed to run delayed recipe tasks", e);
|
||||||
}
|
}
|
||||||
@@ -691,7 +703,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
return optionalItem.map(itemStackCustomItem -> MaterialUtils.getMaterial(itemStackCustomItem.material())).orElse(null);
|
return optionalItem.map(itemStackCustomItem -> MaterialUtils.getMaterial(itemStackCustomItem.material())).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Object> getIngredientLooks(List<Holder<Key>> holders) throws ReflectiveOperationException {
|
private static List<Object> getIngredientLooks(List<Holder<Key>> holders) {
|
||||||
List<Object> itemStacks = new ArrayList<>();
|
List<Object> itemStacks = new ArrayList<>();
|
||||||
for (Holder<Key> holder : holders) {
|
for (Holder<Key> holder : holders) {
|
||||||
ItemStack itemStack = BukkitItemManager.instance().getBuildableItem(holder.value()).get().buildItemStack(ItemBuildContext.EMPTY, 1);
|
ItemStack itemStack = BukkitItemManager.instance().getBuildableItem(holder.value()).get().buildItemStack(ItemBuildContext.EMPTY, 1);
|
||||||
@@ -710,8 +722,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
.map(Optional::get)
|
.map(Optional::get)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
Object shapedRecipe = getNMSRecipe(id);
|
Object shapedRecipe = getOptionalNMSRecipe(id).get();
|
||||||
recipeToMcRecipeHolder.put(recipe, shapedRecipe);
|
|
||||||
if (VersionHelper.isOrAbove1_20_2()) {
|
if (VersionHelper.isOrAbove1_20_2()) {
|
||||||
shapedRecipe = CoreReflections.field$RecipeHolder$recipe.get(shapedRecipe);
|
shapedRecipe = CoreReflections.field$RecipeHolder$recipe.get(shapedRecipe);
|
||||||
}
|
}
|
||||||
@@ -731,8 +742,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
try {
|
try {
|
||||||
List<Ingredient<ItemStack>> actualIngredients = recipe.ingredientsInUse();
|
List<Ingredient<ItemStack>> actualIngredients = recipe.ingredientsInUse();
|
||||||
|
|
||||||
Object shapelessRecipe = getNMSRecipe(id);
|
Object shapelessRecipe = getOptionalNMSRecipe(id).get();
|
||||||
recipeToMcRecipeHolder.put(recipe, shapelessRecipe);
|
|
||||||
if (VersionHelper.isOrAbove1_20_2()) {
|
if (VersionHelper.isOrAbove1_20_2()) {
|
||||||
shapelessRecipe = CoreReflections.field$RecipeHolder$recipe.get(shapelessRecipe);
|
shapelessRecipe = CoreReflections.field$RecipeHolder$recipe.get(shapelessRecipe);
|
||||||
}
|
}
|
||||||
@@ -751,8 +761,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
private static void injectCookingRecipe(Key id, CustomCookingRecipe<ItemStack> recipe) {
|
private static void injectCookingRecipe(Key id, CustomCookingRecipe<ItemStack> recipe) {
|
||||||
try {
|
try {
|
||||||
Ingredient<ItemStack> actualIngredient = recipe.ingredient();
|
Ingredient<ItemStack> actualIngredient = recipe.ingredient();
|
||||||
Object smeltingRecipe = getNMSRecipe(id);
|
Object smeltingRecipe = getOptionalNMSRecipe(id).get();
|
||||||
recipeToMcRecipeHolder.put(recipe, smeltingRecipe);
|
|
||||||
if (VersionHelper.isOrAbove1_20_2()) {
|
if (VersionHelper.isOrAbove1_20_2()) {
|
||||||
smeltingRecipe = CoreReflections.field$RecipeHolder$recipe.get(smeltingRecipe);
|
smeltingRecipe = CoreReflections.field$RecipeHolder$recipe.get(smeltingRecipe);
|
||||||
}
|
}
|
||||||
@@ -771,23 +780,17 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
|||||||
|
|
||||||
// 获取nms配方,请注意1.20.1获取配方本身,而1.20.2+获取的是配方的holder
|
// 获取nms配方,请注意1.20.1获取配方本身,而1.20.2+获取的是配方的holder
|
||||||
// recipe on 1.20.1 and holder on 1.20.2+
|
// recipe on 1.20.1 and holder on 1.20.2+
|
||||||
private static Object getNMSRecipe(Key id) throws ReflectiveOperationException {
|
private static Optional<Object> getOptionalNMSRecipe(Key id) throws ReflectiveOperationException {
|
||||||
if (VersionHelper.isOrAbove1_21_2()) {
|
if (VersionHelper.isOrAbove1_21_2()) {
|
||||||
Object resourceKey = CraftBukkitReflections.method$CraftRecipe$toMinecraft.invoke(null, new NamespacedKey(id.namespace(), id.value()));
|
Object resourceKey = FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.RECIPE, KeyUtils.toResourceLocation(id));
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Optional<Object> optional = (Optional<Object>) CoreReflections.method$RecipeManager$byKey.invoke(nmsRecipeManager, resourceKey);
|
Optional<Object> optional = (Optional<Object>) CoreReflections.method$RecipeManager$byKey.invoke(nmsRecipeManager, resourceKey);
|
||||||
if (optional.isEmpty()) {
|
return optional;
|
||||||
throw new IllegalArgumentException("Recipe " + id + " not found");
|
|
||||||
}
|
|
||||||
return optional.get();
|
|
||||||
} else {
|
} else {
|
||||||
Object resourceLocation = KeyUtils.toResourceLocation(id);
|
Object resourceLocation = KeyUtils.toResourceLocation(id);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Optional<Object> optional = (Optional<Object>) CoreReflections.method$RecipeManager$byKey.invoke(nmsRecipeManager, resourceLocation);
|
Optional<Object> optional = (Optional<Object>) CoreReflections.method$RecipeManager$byKey.invoke(nmsRecipeManager, resourceLocation);
|
||||||
if (optional.isEmpty()) {
|
return optional;
|
||||||
throw new IllegalArgumentException("Recipe " + id + " not found");
|
|
||||||
}
|
|
||||||
return optional.get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import net.momirealms.craftengine.core.item.recipe.Recipe;
|
|||||||
import net.momirealms.craftengine.core.item.recipe.input.CraftingInput;
|
import net.momirealms.craftengine.core.item.recipe.input.CraftingInput;
|
||||||
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
|
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
|
||||||
import net.momirealms.craftengine.core.item.recipe.input.SmithingInput;
|
import net.momirealms.craftengine.core.item.recipe.input.SmithingInput;
|
||||||
|
import net.momirealms.craftengine.core.item.setting.AnvilRepairItem;
|
||||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||||
@@ -32,6 +33,7 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.Campfire;
|
import org.bukkit.block.Campfire;
|
||||||
import org.bukkit.block.Furnace;
|
import org.bukkit.block.Furnace;
|
||||||
|
import org.bukkit.entity.HumanEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
@@ -789,6 +791,49 @@ public class RecipeEventListener implements Listener {
|
|||||||
return new Pair<>(first, second);
|
return new Pair<>(first, second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 不是完美的解决方案,仍然需要更多的探讨
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||||
|
public void onCraft(CraftItemEvent event) {
|
||||||
|
org.bukkit.inventory.Recipe recipe = event.getRecipe();
|
||||||
|
if (!(recipe instanceof ShapelessRecipe) && !(recipe instanceof ShapedRecipe)) return;
|
||||||
|
HumanEntity humanEntity = event.getWhoClicked();
|
||||||
|
if (!(humanEntity instanceof Player player)) return;
|
||||||
|
CraftingInventory inventory = event.getInventory();
|
||||||
|
ItemStack result = inventory.getResult();
|
||||||
|
if (result == null) return;
|
||||||
|
ItemStack[] usedItems = inventory.getMatrix();
|
||||||
|
ItemStack[] replacements = new ItemStack[usedItems.length];
|
||||||
|
boolean hasReplacement = false;
|
||||||
|
for (int i = 0; i < usedItems.length; i++) {
|
||||||
|
ItemStack usedItem = usedItems[i];
|
||||||
|
if (ItemUtils.isEmpty(usedItem)) continue;
|
||||||
|
if (usedItem.getAmount() != 1) continue;
|
||||||
|
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(usedItem);
|
||||||
|
if (wrapped == null) continue;
|
||||||
|
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||||
|
if (optionalCustomItem.isPresent()) {
|
||||||
|
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||||
|
Key remainingItem = customItem.settings().craftRemainder();
|
||||||
|
if (remainingItem != null) {
|
||||||
|
replacements[i] = BukkitItemManager.instance().buildItemStack(remainingItem, this.plugin.adapt(player));
|
||||||
|
hasReplacement = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasReplacement) return;
|
||||||
|
Runnable delayedTask = () -> {
|
||||||
|
for (int i = 0; i < replacements.length; i++) {
|
||||||
|
if (replacements[i] == null) continue;
|
||||||
|
inventory.setItem(i + 1, replacements[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (VersionHelper.isFolia()) {
|
||||||
|
player.getScheduler().run(this.plugin.javaPlugin(), (t) -> delayedTask.run(), () -> {});
|
||||||
|
} else {
|
||||||
|
this.plugin.scheduler().sync().runDelayed(delayedTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onCraftingRecipe(PrepareItemCraftEvent event) {
|
public void onCraftingRecipe(PrepareItemCraftEvent event) {
|
||||||
if (!Config.enableRecipeSystem()) return;
|
if (!Config.enableRecipeSystem()) return;
|
||||||
@@ -843,7 +888,7 @@ public class RecipeEventListener implements Listener {
|
|||||||
try {
|
try {
|
||||||
player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(event.getView());
|
player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(event.getView());
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
plugin.logger().warn("Failed to get inventory viewer", e);
|
this.plugin.logger().warn("Failed to get inventory viewer", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -854,14 +899,18 @@ public class RecipeEventListener implements Listener {
|
|||||||
if (ceRecipe != null) {
|
if (ceRecipe != null) {
|
||||||
inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
||||||
serverPlayer.setLastUsedRecipe(ceRecipe.id());
|
serverPlayer.setLastUsedRecipe(ceRecipe.id());
|
||||||
|
if (!ceRecipe.id().equals(recipeId)) {
|
||||||
correctCraftingRecipeUsed(inventory, ceRecipe);
|
correctCraftingRecipeUsed(inventory, ceRecipe);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPED, input, lastRecipe);
|
ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPED, input, lastRecipe);
|
||||||
if (ceRecipe != null) {
|
if (ceRecipe != null) {
|
||||||
inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
||||||
serverPlayer.setLastUsedRecipe(ceRecipe.id());
|
serverPlayer.setLastUsedRecipe(ceRecipe.id());
|
||||||
|
if (!ceRecipe.id().equals(recipeId)) {
|
||||||
correctCraftingRecipeUsed(inventory, ceRecipe);
|
correctCraftingRecipeUsed(inventory, ceRecipe);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// clear result if not met
|
// clear result if not met
|
||||||
@@ -869,9 +918,8 @@ public class RecipeEventListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void correctCraftingRecipeUsed(CraftingInventory inventory, Recipe<ItemStack> recipe) {
|
private void correctCraftingRecipeUsed(CraftingInventory inventory, Recipe<ItemStack> recipe) {
|
||||||
Object holderOrRecipe = recipeManager.nmsRecipeHolderByRecipe(recipe);
|
Object holderOrRecipe = this.recipeManager.nmsRecipeHolderByRecipe(recipe);
|
||||||
if (holderOrRecipe == null) {
|
if (holderOrRecipe == null) {
|
||||||
// it's a vanilla recipe but not injected
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -922,20 +970,21 @@ public class RecipeEventListener implements Listener {
|
|||||||
CustomSmithingTransformRecipe<ItemStack> transformRecipe = (CustomSmithingTransformRecipe<ItemStack>) ceRecipe;
|
CustomSmithingTransformRecipe<ItemStack> transformRecipe = (CustomSmithingTransformRecipe<ItemStack>) ceRecipe;
|
||||||
ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base));
|
ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base));
|
||||||
event.setResult(processed);
|
event.setResult(processed);
|
||||||
|
if (!ceRecipe.id().equals(recipeId)) {
|
||||||
correctSmithingRecipeUsed(inventory, ceRecipe);
|
correctSmithingRecipeUsed(inventory, ceRecipe);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void correctSmithingRecipeUsed(SmithingInventory inventory, Recipe<ItemStack> recipe) {
|
private void correctSmithingRecipeUsed(SmithingInventory inventory, Recipe<ItemStack> recipe) {
|
||||||
Object holderOrRecipe = recipeManager.nmsRecipeHolderByRecipe(recipe);
|
Object holderOrRecipe = this.recipeManager.nmsRecipeHolderByRecipe(recipe);
|
||||||
if (holderOrRecipe == null) {
|
if (holderOrRecipe == null) {
|
||||||
// it's a vanilla recipe but not injected
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Object resultInventory = CraftBukkitReflections.field$CraftResultInventory$resultInventory.get(inventory);
|
Object resultInventory = CraftBukkitReflections.field$CraftResultInventory$resultInventory.get(inventory);
|
||||||
CoreReflections.field$ResultContainer$recipeUsed.set(resultInventory, holderOrRecipe);
|
CoreReflections.field$ResultContainer$recipeUsed.set(resultInventory, holderOrRecipe);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
plugin.logger().warn("Failed to correct used recipe", e);
|
this.plugin.logger().warn("Failed to correct used recipe", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ import org.bukkit.plugin.java.JavaPlugin;
|
|||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -68,8 +67,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
|||||||
private SchedulerTask tickTask;
|
private SchedulerTask tickTask;
|
||||||
private boolean successfullyLoaded = false;
|
private boolean successfullyLoaded = false;
|
||||||
private boolean successfullyEnabled = false;
|
private boolean successfullyEnabled = false;
|
||||||
private boolean requiresRestart = false;
|
|
||||||
private boolean hasMod = false;
|
|
||||||
private AntiGriefLib antiGrief;
|
private AntiGriefLib antiGrief;
|
||||||
private JavaPlugin javaPlugin;
|
private JavaPlugin javaPlugin;
|
||||||
private final Path dataFolderPath;
|
private final Path dataFolderPath;
|
||||||
@@ -90,16 +87,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
|||||||
super.logger = logger;
|
super.logger = logger;
|
||||||
super.platform = new BukkitPlatform();
|
super.platform = new BukkitPlatform();
|
||||||
super.scheduler = new BukkitSchedulerAdapter(this);
|
super.scheduler = new BukkitSchedulerAdapter(this);
|
||||||
// find mod class if present
|
|
||||||
Class<?> modClass = ReflectionUtils.getClazz(MOD_CLASS);
|
|
||||||
if (modClass != null) {
|
|
||||||
Field isSuccessfullyRegistered = ReflectionUtils.getDeclaredField(modClass, "isSuccessfullyRegistered");
|
|
||||||
try {
|
|
||||||
requiresRestart = !(boolean) isSuccessfullyRegistered.get(null);
|
|
||||||
hasMod = true;
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Class<?> compatibilityClass = Objects.requireNonNull(ReflectionUtils.getClazz(COMPATIBILITY_CLASS), "Compatibility class not found");
|
Class<?> compatibilityClass = Objects.requireNonNull(ReflectionUtils.getClazz(COMPATIBILITY_CLASS), "Compatibility class not found");
|
||||||
try {
|
try {
|
||||||
super.compatibilityManager = (CompatibilityManager) Objects.requireNonNull(ReflectionUtils.getConstructor(compatibilityClass, 0)).newInstance(this);
|
super.compatibilityManager = (CompatibilityManager) Objects.requireNonNull(ReflectionUtils.getConstructor(compatibilityClass, 0)).newInstance(this);
|
||||||
@@ -132,7 +119,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
|||||||
if (super.blockManager == null) {
|
if (super.blockManager == null) {
|
||||||
injectRegistries();
|
injectRegistries();
|
||||||
}
|
}
|
||||||
if (this.requiresRestart) return;
|
|
||||||
try {
|
try {
|
||||||
WorldStorageInjector.init();
|
WorldStorageInjector.init();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -177,17 +163,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.successfullyEnabled = true;
|
this.successfullyEnabled = true;
|
||||||
if (this.requiresRestart) {
|
|
||||||
logger().warn(" ");
|
|
||||||
logger().warn(" ");
|
|
||||||
logger().warn(" ");
|
|
||||||
logger().warn("This is the first time you have installed CraftEngine. A restart is required to apply the changes.");
|
|
||||||
logger().warn(" ");
|
|
||||||
logger().warn(" ");
|
|
||||||
logger().warn(" ");
|
|
||||||
Bukkit.getServer().shutdown();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.successfullyLoaded) {
|
if (!this.successfullyLoaded) {
|
||||||
logger().severe(" ");
|
logger().severe(" ");
|
||||||
logger().severe(" ");
|
logger().severe(" ");
|
||||||
@@ -390,14 +365,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasMod() {
|
|
||||||
return hasMod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean requiresRestart() {
|
|
||||||
return requiresRestart;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AntiGriefLib antiGrief() {
|
public AntiGriefLib antiGrief() {
|
||||||
if (this.antiGrief == null) {
|
if (this.antiGrief == null) {
|
||||||
this.antiGrief = AntiGriefLib.builder(this.javaPlugin)
|
this.antiGrief = AntiGriefLib.builder(this.javaPlugin)
|
||||||
|
|||||||
@@ -1,12 +1,32 @@
|
|||||||
package net.momirealms.craftengine.bukkit.plugin;
|
package net.momirealms.craftengine.bukkit.plugin;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
|
||||||
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
import net.momirealms.craftengine.core.plugin.Platform;
|
import net.momirealms.craftengine.core.plugin.Platform;
|
||||||
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class BukkitPlatform implements Platform {
|
public class BukkitPlatform implements Platform {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispatchCommand(String command) {
|
public void dispatchCommand(String command) {
|
||||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command);
|
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Object nbt2Java(String nbt) {
|
||||||
|
try {
|
||||||
|
Object tag = FastNMS.INSTANCE.method$TagParser$parseCompoundFully("{\"root\":" + nbt + "}");
|
||||||
|
Map<String, Object> map = (Map<String, Object>) MRegistryOps.NBT.convertTo(MRegistryOps.JAVA, tag);
|
||||||
|
return map.get("root");
|
||||||
|
} catch (CommandSyntaxException e) {
|
||||||
|
CraftEngine.instance().debug(e::getMessage);
|
||||||
|
throw new LocalizedResourceConfigException("warning.config.template.argument.default_value.invalid_syntax", e, nbt);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
|
|||||||
new DebugSpawnFurnitureCommand(this, plugin),
|
new DebugSpawnFurnitureCommand(this, plugin),
|
||||||
new DebugTargetBlockCommand(this, plugin),
|
new DebugTargetBlockCommand(this, plugin),
|
||||||
new DebugIsSectionInjectedCommand(this, plugin),
|
new DebugIsSectionInjectedCommand(this, plugin),
|
||||||
|
new DebugMigrateTemplatesCommand(this, plugin),
|
||||||
|
new DebugEntityId2UUIDCommand(this, plugin),
|
||||||
new TotemAnimationCommand(this, plugin),
|
new TotemAnimationCommand(this, plugin),
|
||||||
new EnableResourceCommand(this, plugin),
|
new EnableResourceCommand(this, plugin),
|
||||||
new DisableResourceCommand(this, plugin),
|
new DisableResourceCommand(this, plugin),
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||||
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
|
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.incendo.cloud.Command;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
import org.incendo.cloud.bukkit.parser.WorldParser;
|
||||||
|
import org.incendo.cloud.parser.standard.IntegerParser;
|
||||||
|
|
||||||
|
public class DebugEntityId2UUIDCommand extends BukkitCommandFeature<CommandSender> {
|
||||||
|
|
||||||
|
public DebugEntityId2UUIDCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
|
||||||
|
super(commandManager, plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||||
|
return builder
|
||||||
|
.required("world", WorldParser.worldParser())
|
||||||
|
.required("entityId", IntegerParser.integerParser())
|
||||||
|
.handler(context -> {
|
||||||
|
World world = context.get("world");
|
||||||
|
int entityId = context.get("entityId");
|
||||||
|
Entity entity = FastNMS.INSTANCE.getBukkitEntityById(world, entityId);
|
||||||
|
if (entity == null) {
|
||||||
|
context.sender().sendMessage("entity not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Location location = entity.getLocation();
|
||||||
|
context.sender().sendMessage(
|
||||||
|
String.format(
|
||||||
|
"""
|
||||||
|
===========================
|
||||||
|
uuid: %s
|
||||||
|
name: %s
|
||||||
|
location: %s,%s,%s
|
||||||
|
type: %s
|
||||||
|
===========================
|
||||||
|
""",
|
||||||
|
entity.getUniqueId(),
|
||||||
|
entity.getName(),
|
||||||
|
location.x(), location.y(), location.z(),
|
||||||
|
entity.getType()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFeatureID() {
|
||||||
|
return "debug_entity_id_to_uuid";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||||
|
import net.momirealms.craftengine.core.pack.Pack;
|
||||||
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
|
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||||
|
import net.momirealms.craftengine.core.util.FileUtils;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.incendo.cloud.Command;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class DebugMigrateTemplatesCommand extends BukkitCommandFeature<CommandSender> {
|
||||||
|
private static final Pattern PATTERN = Pattern.compile("(?<!\\$)\\{([^}]+)}");
|
||||||
|
|
||||||
|
public DebugMigrateTemplatesCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
|
||||||
|
super(commandManager, plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||||
|
return builder
|
||||||
|
.handler(context -> {
|
||||||
|
for (Pack pack : BukkitCraftEngine.instance().packManager().loadedPacks()) {
|
||||||
|
for (Path file : FileUtils.getYmlConfigsDeeply(pack.configurationFolder())) {
|
||||||
|
try {
|
||||||
|
Files.writeString(file, replacePlaceholders(Files.readString(file)));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.sender().sendMessage("Done");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFeatureID() {
|
||||||
|
return "debug_migrate_templates";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String replacePlaceholders(String input) {
|
||||||
|
if (input == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Matcher matcher = PATTERN.matcher(input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (matcher.find()) {
|
||||||
|
// 将 {xxx} 替换为 ${xxx}
|
||||||
|
matcher.appendReplacement(sb, "\\${" + matcher.group(1) + "}");
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,7 +54,7 @@ public class DebugSpawnFurnitureCommand extends BukkitCommandFeature<CommandSend
|
|||||||
}
|
}
|
||||||
Location location = context.get("location");
|
Location location = context.get("location");
|
||||||
CustomFurniture customFurniture = optionalCustomFurniture.get();
|
CustomFurniture customFurniture = optionalCustomFurniture.get();
|
||||||
AnchorType anchorType = (AnchorType) context.optional("anchor-type").orElse(customFurniture.getAnyPlacement());
|
AnchorType anchorType = (AnchorType) context.optional("anchor-type").orElse(customFurniture.getAnyAnchorType());
|
||||||
boolean playSound = context.flags().hasFlag("silent");
|
boolean playSound = context.flags().hasFlag("silent");
|
||||||
CraftEngineFurniture.place(location, customFurniture, anchorType, playSound);
|
CraftEngineFurniture.place(location, customFurniture, anchorType, playSound);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class DisableResourceCommand extends BukkitCommandFeature<CommandSender>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
YamlDocument document = plugin().config().loadYamlData(packMetaPath.toFile());
|
YamlDocument document = plugin().config().loadYamlData(packMetaPath);
|
||||||
document.set("enable", false);
|
document.set("enable", false);
|
||||||
try {
|
try {
|
||||||
document.save(packMetaPath.toFile());
|
document.save(packMetaPath.toFile());
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class EnableResourceCommand extends BukkitCommandFeature<CommandSender> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
YamlDocument document = plugin().config().loadYamlData(packMetaPath.toFile());
|
YamlDocument document = plugin().config().loadYamlData(packMetaPath);
|
||||||
document.set("enable", true);
|
document.set("enable", true);
|
||||||
try {
|
try {
|
||||||
document.save(packMetaPath.toFile());
|
document.save(packMetaPath.toFile());
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
|||||||
import net.momirealms.craftengine.bukkit.util.NoteBlockChainUpdateUtils;
|
import net.momirealms.craftengine.bukkit.util.NoteBlockChainUpdateUtils;
|
||||||
import net.momirealms.craftengine.core.block.*;
|
import net.momirealms.craftengine.core.block.*;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
|
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ObjectHolder;
|
import net.momirealms.craftengine.core.util.ObjectHolder;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
@@ -36,6 +37,7 @@ public final class BlockGenerator {
|
|||||||
private static Field field$CraftEngineBlock$behavior;
|
private static Field field$CraftEngineBlock$behavior;
|
||||||
private static Field field$CraftEngineBlock$shape;
|
private static Field field$CraftEngineBlock$shape;
|
||||||
private static Field field$CraftEngineBlock$isNoteBlock;
|
private static Field field$CraftEngineBlock$isNoteBlock;
|
||||||
|
private static Field field$CraftEngineBlock$isTripwire;
|
||||||
|
|
||||||
public static void init() throws ReflectiveOperationException {
|
public static void init() throws ReflectiveOperationException {
|
||||||
ByteBuddy byteBuddy = new ByteBuddy(ClassFileVersion.JAVA_V17);
|
ByteBuddy byteBuddy = new ByteBuddy(ClassFileVersion.JAVA_V17);
|
||||||
@@ -48,6 +50,7 @@ public final class BlockGenerator {
|
|||||||
.defineField("behaviorHolder", ObjectHolder.class, Visibility.PUBLIC)
|
.defineField("behaviorHolder", ObjectHolder.class, Visibility.PUBLIC)
|
||||||
.defineField("shapeHolder", ObjectHolder.class, Visibility.PUBLIC)
|
.defineField("shapeHolder", ObjectHolder.class, Visibility.PUBLIC)
|
||||||
.defineField("isClientSideNoteBlock", boolean.class, Visibility.PUBLIC)
|
.defineField("isClientSideNoteBlock", boolean.class, Visibility.PUBLIC)
|
||||||
|
.defineField("isClientSideTripwire", boolean.class, Visibility.PUBLIC)
|
||||||
// should always implement this interface
|
// should always implement this interface
|
||||||
.implement(CoreReflections.clazz$Fallable)
|
.implement(CoreReflections.clazz$Fallable)
|
||||||
.implement(CoreReflections.clazz$BonemealableBlock)
|
.implement(CoreReflections.clazz$BonemealableBlock)
|
||||||
@@ -55,13 +58,15 @@ public final class BlockGenerator {
|
|||||||
// internal interfaces
|
// internal interfaces
|
||||||
.implement(BehaviorHolder.class)
|
.implement(BehaviorHolder.class)
|
||||||
.implement(ShapeHolder.class)
|
.implement(ShapeHolder.class)
|
||||||
.implement(NoteBlockIndicator.class)
|
.implement(ChainUpdateBlockIndicator.class)
|
||||||
.method(ElementMatchers.named("getBehaviorHolder"))
|
.method(ElementMatchers.named("getBehaviorHolder"))
|
||||||
.intercept(FieldAccessor.ofField("behaviorHolder"))
|
.intercept(FieldAccessor.ofField("behaviorHolder"))
|
||||||
.method(ElementMatchers.named("getShapeHolder"))
|
.method(ElementMatchers.named("getShapeHolder"))
|
||||||
.intercept(FieldAccessor.ofField("shapeHolder"))
|
.intercept(FieldAccessor.ofField("shapeHolder"))
|
||||||
.method(ElementMatchers.named("isNoteBlock"))
|
.method(ElementMatchers.named("isNoteBlock"))
|
||||||
.intercept(FieldAccessor.ofField("isClientSideNoteBlock"))
|
.intercept(FieldAccessor.ofField("isClientSideNoteBlock"))
|
||||||
|
.method(ElementMatchers.named("isTripwire"))
|
||||||
|
.intercept(FieldAccessor.ofField("isClientSideTripwire"))
|
||||||
// getShape
|
// getShape
|
||||||
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$getShape))
|
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$getShape))
|
||||||
.intercept(MethodDelegation.to(GetShapeInterceptor.INSTANCE))
|
.intercept(MethodDelegation.to(GetShapeInterceptor.INSTANCE))
|
||||||
@@ -142,6 +147,7 @@ public final class BlockGenerator {
|
|||||||
field$CraftEngineBlock$behavior = clazz$CraftEngineBlock.getField("behaviorHolder");
|
field$CraftEngineBlock$behavior = clazz$CraftEngineBlock.getField("behaviorHolder");
|
||||||
field$CraftEngineBlock$shape = clazz$CraftEngineBlock.getField("shapeHolder");
|
field$CraftEngineBlock$shape = clazz$CraftEngineBlock.getField("shapeHolder");
|
||||||
field$CraftEngineBlock$isNoteBlock = clazz$CraftEngineBlock.getField("isClientSideNoteBlock");
|
field$CraftEngineBlock$isNoteBlock = clazz$CraftEngineBlock.getField("isClientSideNoteBlock");
|
||||||
|
field$CraftEngineBlock$isTripwire = clazz$CraftEngineBlock.getField("isClientSideTripwire");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object generateBlock(Key replacedBlock, Object ownerBlock, Object properties) throws Throwable {
|
public static Object generateBlock(Key replacedBlock, Object ownerBlock, Object properties) throws Throwable {
|
||||||
@@ -155,19 +161,29 @@ public final class BlockGenerator {
|
|||||||
field$CraftEngineBlock$behavior.set(newBlockInstance, behaviorHolder);
|
field$CraftEngineBlock$behavior.set(newBlockInstance, behaviorHolder);
|
||||||
field$CraftEngineBlock$shape.set(newBlockInstance, shapeHolder);
|
field$CraftEngineBlock$shape.set(newBlockInstance, shapeHolder);
|
||||||
field$CraftEngineBlock$isNoteBlock.set(newBlockInstance, replacedBlock.equals(BlockKeys.NOTE_BLOCK));
|
field$CraftEngineBlock$isNoteBlock.set(newBlockInstance, replacedBlock.equals(BlockKeys.NOTE_BLOCK));
|
||||||
|
field$CraftEngineBlock$isTripwire.set(newBlockInstance, replacedBlock.equals(BlockKeys.TRIPWIRE));
|
||||||
return newBlockInstance;
|
return newBlockInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UpdateShapeInterceptor {
|
public static class UpdateShapeInterceptor {
|
||||||
public static final UpdateShapeInterceptor INSTANCE = new UpdateShapeInterceptor();
|
public static final UpdateShapeInterceptor INSTANCE = new UpdateShapeInterceptor();
|
||||||
public static final int levelIndex = VersionHelper.isOrAbove1_21_2() ? 1 : 3;
|
public static final int levelIndex = VersionHelper.isOrAbove1_21_2() ? 1 : 3;
|
||||||
|
public static final int directionIndex = VersionHelper.isOrAbove1_21_2() ? 4 : 1;
|
||||||
|
public static final int posIndex = VersionHelper.isOrAbove1_21_2() ? 3 : 4;
|
||||||
|
|
||||||
@RuntimeType
|
@RuntimeType
|
||||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) throws Exception {
|
public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) {
|
||||||
ObjectHolder<BlockBehavior> holder = ((BehaviorHolder) thisObj).getBehaviorHolder();
|
ObjectHolder<BlockBehavior> holder = ((BehaviorHolder) thisObj).getBehaviorHolder();
|
||||||
if (((NoteBlockIndicator) thisObj).isNoteBlock() && CoreReflections.clazz$ServerLevel.isInstance(args[levelIndex])) {
|
ChainUpdateBlockIndicator indicator = (ChainUpdateBlockIndicator) thisObj;
|
||||||
|
if (indicator.isNoteBlock()) {
|
||||||
|
if (CoreReflections.clazz$ServerLevel.isInstance(args[levelIndex])) {
|
||||||
startNoteBlockChain(args);
|
startNoteBlockChain(args);
|
||||||
}
|
}
|
||||||
|
} else if (indicator.isTripwire()) {
|
||||||
|
if (CoreReflections.clazz$ServerLevel.isInstance(args[posIndex])) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return holder.value().updateShape(thisObj, args, superMethod);
|
return holder.value().updateShape(thisObj, args, superMethod);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -175,30 +191,20 @@ public final class BlockGenerator {
|
|||||||
return args[0];
|
return args[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void startNoteBlockChain(Object[] args) throws ReflectiveOperationException {
|
private static void startNoteBlockChain(Object[] args) {
|
||||||
Object direction;
|
Object direction = args[directionIndex];
|
||||||
Object serverLevel;
|
Object serverLevel = args[levelIndex];
|
||||||
Object blockPos;
|
Object blockPos = args[posIndex];
|
||||||
if (VersionHelper.isOrAbove1_21_2()) {
|
|
||||||
direction = args[4];
|
|
||||||
serverLevel = args[1];
|
|
||||||
blockPos = args[3];
|
|
||||||
} else {
|
|
||||||
direction = args[1];
|
|
||||||
serverLevel = args[3];
|
|
||||||
blockPos = args[4];
|
|
||||||
}
|
|
||||||
int id = (int) CoreReflections.field$Direction$data3d.get(direction);
|
|
||||||
// Y axis
|
// Y axis
|
||||||
if (id == 0 || id == 1) {
|
if (direction == CoreReflections.instance$Direction$DOWN) {
|
||||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel);
|
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel);
|
||||||
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos);
|
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos);
|
||||||
if (id == 1) {
|
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, CoreReflections.instance$Direction$UP, blockPos, Config.maxNoteBlockChainUpdate());
|
||||||
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, CoreReflections.instance$Direction$DOWN, blockPos, 0);
|
} else if (direction == CoreReflections.instance$Direction$UP) {
|
||||||
} else {
|
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel);
|
||||||
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, CoreReflections.instance$Direction$UP, blockPos, 0);
|
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos);
|
||||||
|
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, CoreReflections.instance$Direction$DOWN, blockPos, Config.maxNoteBlockChainUpdate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ public interface InjectedCacheCheck {
|
|||||||
|
|
||||||
void recipeType(Object recipeType);
|
void recipeType(Object recipeType);
|
||||||
|
|
||||||
|
Key customRecipeType();
|
||||||
|
|
||||||
|
void customRecipeType(Key customRecipeType);
|
||||||
|
|
||||||
Object lastRecipe();
|
Object lastRecipe();
|
||||||
|
|
||||||
void lastRecipe(Object lastRecipe);
|
void lastRecipe(Object lastRecipe);
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager;
|
|||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRecipeTypes;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRecipeTypes;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||||
import net.momirealms.craftengine.core.item.Item;
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
import net.momirealms.craftengine.core.item.recipe.CustomCookingRecipe;
|
import net.momirealms.craftengine.core.item.recipe.CustomCookingRecipe;
|
||||||
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
|
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
|
||||||
@@ -28,7 +30,6 @@ import net.momirealms.craftengine.core.util.ReflectionUtils;
|
|||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class RecipeInjector {
|
public class RecipeInjector {
|
||||||
@@ -41,17 +42,23 @@ public class RecipeInjector {
|
|||||||
.name("net.momirealms.craftengine.bukkit.entity.InjectedCacheChecker")
|
.name("net.momirealms.craftengine.bukkit.entity.InjectedCacheChecker")
|
||||||
.implement(CoreReflections.clazz$RecipeManager$CachedCheck)
|
.implement(CoreReflections.clazz$RecipeManager$CachedCheck)
|
||||||
.implement(InjectedCacheCheck.class)
|
.implement(InjectedCacheCheck.class)
|
||||||
|
|
||||||
.defineField("recipeType", Object.class, Visibility.PUBLIC)
|
.defineField("recipeType", Object.class, Visibility.PUBLIC)
|
||||||
.method(ElementMatchers.named("recipeType"))
|
.method(ElementMatchers.named("recipeType"))
|
||||||
.intercept(FieldAccessor.ofField("recipeType"))
|
.intercept(FieldAccessor.ofField("recipeType"))
|
||||||
|
|
||||||
|
.defineField("customRecipeType", Key.class, Visibility.PUBLIC)
|
||||||
|
.method(ElementMatchers.named("customRecipeType"))
|
||||||
|
.intercept(FieldAccessor.ofField("customRecipeType"))
|
||||||
|
|
||||||
.defineField("lastRecipe", Object.class, Visibility.PUBLIC)
|
.defineField("lastRecipe", Object.class, Visibility.PUBLIC)
|
||||||
.method(ElementMatchers.named("lastRecipe"))
|
.method(ElementMatchers.named("lastRecipe"))
|
||||||
.intercept(FieldAccessor.ofField("lastRecipe"))
|
.intercept(FieldAccessor.ofField("lastRecipe"))
|
||||||
.method(ElementMatchers.named("setLastRecipe"))
|
|
||||||
.intercept(FieldAccessor.ofField("lastRecipe"))
|
|
||||||
.defineField("lastCustomRecipe", Key.class, Visibility.PUBLIC)
|
.defineField("lastCustomRecipe", Key.class, Visibility.PUBLIC)
|
||||||
.method(ElementMatchers.named("lastCustomRecipe"))
|
.method(ElementMatchers.named("lastCustomRecipe"))
|
||||||
.intercept(FieldAccessor.ofField("lastCustomRecipe"))
|
.intercept(FieldAccessor.ofField("lastCustomRecipe"))
|
||||||
|
|
||||||
.method(ElementMatchers.named("getRecipeFor").or(ElementMatchers.named("a")))
|
.method(ElementMatchers.named("getRecipeFor").or(ElementMatchers.named("a")))
|
||||||
.intercept(MethodDelegation.to(
|
.intercept(MethodDelegation.to(
|
||||||
VersionHelper.isOrAbove1_21_2() ?
|
VersionHelper.isOrAbove1_21_2() ?
|
||||||
@@ -73,50 +80,60 @@ public class RecipeInjector {
|
|||||||
if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected
|
if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected
|
||||||
Object recipeType = FastNMS.INSTANCE.field$AbstractFurnaceBlockEntity$recipeType(entity);
|
Object recipeType = FastNMS.INSTANCE.field$AbstractFurnaceBlockEntity$recipeType(entity);
|
||||||
InjectedCacheCheck injectedChecker = (InjectedCacheCheck) ReflectionUtils.UNSAFE.allocateInstance(clazz$InjectedCacheChecker);
|
InjectedCacheCheck injectedChecker = (InjectedCacheCheck) ReflectionUtils.UNSAFE.allocateInstance(clazz$InjectedCacheChecker);
|
||||||
injectedChecker.recipeType(recipeType);
|
if (recipeType == MRecipeTypes.SMELTING) {
|
||||||
|
injectedChecker.customRecipeType(RecipeTypes.SMELTING);
|
||||||
|
injectedChecker.recipeType(MRecipeTypes.SMELTING);
|
||||||
|
} else if (recipeType == MRecipeTypes.BLASTING) {
|
||||||
|
injectedChecker.customRecipeType(RecipeTypes.BLASTING);
|
||||||
|
injectedChecker.recipeType(MRecipeTypes.BLASTING);
|
||||||
|
} else if (recipeType == MRecipeTypes.SMOKING) {
|
||||||
|
injectedChecker.customRecipeType(RecipeTypes.SMOKING);
|
||||||
|
injectedChecker.recipeType(MRecipeTypes.SMOKING);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("RecipeType " + recipeType + " not supported");
|
||||||
|
}
|
||||||
CoreReflections.field$AbstractFurnaceBlockEntity$quickCheck.set(entity, injectedChecker);
|
CoreReflections.field$AbstractFurnaceBlockEntity$quickCheck.set(entity, injectedChecker);
|
||||||
} else if (!VersionHelper.isOrAbove1_21_2() && CoreReflections.clazz$CampfireBlockEntity.isInstance(entity)) {
|
} else if (!VersionHelper.isOrAbove1_21_2() && CoreReflections.clazz$CampfireBlockEntity.isInstance(entity)) {
|
||||||
Object quickCheck = CoreReflections.field$CampfireBlockEntity$quickCheck.get(entity);
|
Object quickCheck = CoreReflections.field$CampfireBlockEntity$quickCheck.get(entity);
|
||||||
if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected
|
if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected
|
||||||
InjectedCacheCheck injectedChecker = (InjectedCacheCheck) ReflectionUtils.UNSAFE.allocateInstance(clazz$InjectedCacheChecker);
|
InjectedCacheCheck injectedChecker = (InjectedCacheCheck) ReflectionUtils.UNSAFE.allocateInstance(clazz$InjectedCacheChecker);
|
||||||
|
injectedChecker.customRecipeType(RecipeTypes.CAMPFIRE_COOKING);
|
||||||
injectedChecker.recipeType(MRecipeTypes.CAMPFIRE_COOKING);
|
injectedChecker.recipeType(MRecipeTypes.CAMPFIRE_COOKING);
|
||||||
CoreReflections.field$CampfireBlockEntity$quickCheck.set(entity, injectedChecker);
|
CoreReflections.field$CampfireBlockEntity$quickCheck.set(entity, injectedChecker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public static class GetRecipeForMethodInterceptor1_20 {
|
public static class GetRecipeForMethodInterceptor1_20 {
|
||||||
public static final GetRecipeForMethodInterceptor1_20 INSTANCE = new GetRecipeForMethodInterceptor1_20();
|
public static final GetRecipeForMethodInterceptor1_20 INSTANCE = new GetRecipeForMethodInterceptor1_20();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@RuntimeType
|
@RuntimeType
|
||||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args) throws Exception {
|
public Object intercept(@This Object thisObj, @AllArguments Object[] args) {
|
||||||
Object mcRecipeManager = BukkitRecipeManager.nmsRecipeManager();
|
|
||||||
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
||||||
Object type = injectedCacheCheck.recipeType();
|
Object lastRecipeResourceLocation = injectedCacheCheck.lastRecipe();
|
||||||
Object lastRecipe = injectedCacheCheck.lastRecipe();
|
Optional<Pair<Object, Object>> optionalRecipe = FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.nmsRecipeManager(), injectedCacheCheck.recipeType(), args[0], args[1], lastRecipeResourceLocation);
|
||||||
Optional<Pair<Object, Object>> optionalRecipe = FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(mcRecipeManager, type, args[0], args[1], lastRecipe);
|
if (optionalRecipe.isEmpty()) {
|
||||||
if (optionalRecipe.isPresent()) {
|
return Optional.empty();
|
||||||
Pair<Object, Object> pair = optionalRecipe.get();
|
}
|
||||||
Object resourceLocation = pair.getFirst();
|
|
||||||
Key recipeId = Key.of(resourceLocation.toString());
|
Pair<Object, Object> resourceLocationAndRecipe = optionalRecipe.get();
|
||||||
|
Object rawRecipeResourceLocation = resourceLocationAndRecipe.getFirst();
|
||||||
|
Key rawRecipeKey = Key.of(rawRecipeResourceLocation.toString());
|
||||||
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
||||||
|
|
||||||
ItemStack itemStack;
|
boolean isCustom = recipeManager.isCustomRecipe(rawRecipeKey);
|
||||||
List<Object> items;
|
|
||||||
if (type == MRecipeTypes.CAMPFIRE_COOKING) {
|
|
||||||
items = (List<Object>) CoreReflections.field$SimpleContainer$items.get(args[0]);
|
|
||||||
} else {
|
|
||||||
items = (List<Object>) CoreReflections.field$AbstractFurnaceBlockEntity$items.get(args[0]);
|
|
||||||
}
|
|
||||||
itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(items.get(0));
|
|
||||||
|
|
||||||
// it's a recipe from other plugins
|
|
||||||
boolean isCustom = recipeManager.isCustomRecipe(recipeId);
|
|
||||||
if (!isCustom) {
|
if (!isCustom) {
|
||||||
injectedCacheCheck.lastRecipe(resourceLocation);
|
injectedCacheCheck.lastRecipe(rawRecipeResourceLocation);
|
||||||
return Optional.of(pair.getSecond());
|
return Optional.of(resourceLocationAndRecipe.getSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(
|
||||||
|
injectedCacheCheck.recipeType() == MRecipeTypes.CAMPFIRE_COOKING ?
|
||||||
|
FastNMS.INSTANCE.field$SimpleContainer$items(args[0]).getFirst() :
|
||||||
|
FastNMS.INSTANCE.field$AbstractFurnaceBlockEntity$getItem(args[0], 0)
|
||||||
|
);
|
||||||
|
|
||||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||||
if (idHolder.isEmpty()) {
|
if (idHolder.isEmpty()) {
|
||||||
@@ -124,64 +141,47 @@ public class RecipeInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||||
CustomCookingRecipe<ItemStack> ceRecipe;
|
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe());
|
||||||
Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe();
|
|
||||||
if (type == MRecipeTypes.SMELTING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.BLASTING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.SMOKING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.CAMPFIRE_COOKING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input, lastCustomRecipe);
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
if (ceRecipe == null) {
|
if (ceRecipe == null) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache recipes, it might be incorrect on reloading
|
|
||||||
injectedCacheCheck.lastCustomRecipe(ceRecipe.id());
|
injectedCacheCheck.lastCustomRecipe(ceRecipe.id());
|
||||||
// It doesn't matter at all
|
if (!ceRecipe.id().equals(rawRecipeKey)) {
|
||||||
injectedCacheCheck.lastRecipe(resourceLocation);
|
injectedCacheCheck.lastRecipe(KeyUtils.toResourceLocation(ceRecipe.id()));
|
||||||
return Optional.of(Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)).orElse(pair.getSecond()));
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
return Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public static class GetRecipeForMethodInterceptor1_20_5 {
|
public static class GetRecipeForMethodInterceptor1_20_5 {
|
||||||
public static final GetRecipeForMethodInterceptor1_20_5 INSTANCE = new GetRecipeForMethodInterceptor1_20_5();
|
public static final GetRecipeForMethodInterceptor1_20_5 INSTANCE = new GetRecipeForMethodInterceptor1_20_5();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@RuntimeType
|
@RuntimeType
|
||||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args) throws Exception {
|
public Object intercept(@This Object thisObj, @AllArguments Object[] args) {
|
||||||
Object mcRecipeManager = BukkitRecipeManager.nmsRecipeManager();
|
|
||||||
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
||||||
Object type = injectedCacheCheck.recipeType();
|
Object lastRecipeResourceLocation = injectedCacheCheck.lastRecipe();
|
||||||
Object lastRecipe = injectedCacheCheck.lastRecipe();
|
Optional<Object> optionalRecipe = (Optional<Object>) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.nmsRecipeManager(), injectedCacheCheck.recipeType(), args[0], args[1], lastRecipeResourceLocation);
|
||||||
Optional<Object> optionalRecipe = (Optional<Object>) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(mcRecipeManager, type, args[0], args[1], lastRecipe);
|
if (optionalRecipe.isEmpty()) {
|
||||||
if (optionalRecipe.isPresent()) {
|
return Optional.empty();
|
||||||
Object holder = optionalRecipe.get();
|
|
||||||
Object id = FastNMS.INSTANCE.field$RecipeHolder$id(holder);
|
|
||||||
Key recipeId = Key.of(id.toString());
|
|
||||||
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
|
||||||
|
|
||||||
ItemStack itemStack;
|
|
||||||
List<Object> items;
|
|
||||||
if (type == MRecipeTypes.CAMPFIRE_COOKING) {
|
|
||||||
items = (List<Object>) CoreReflections.field$SimpleContainer$items.get(args[0]);
|
|
||||||
} else {
|
|
||||||
items = (List<Object>) CoreReflections.field$AbstractFurnaceBlockEntity$items.get(args[0]);
|
|
||||||
}
|
}
|
||||||
itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(items.get(0));
|
|
||||||
|
|
||||||
// it's a recipe from other plugins
|
Object rawRecipeHolder = optionalRecipe.get();
|
||||||
boolean isCustom = recipeManager.isCustomRecipe(recipeId);
|
Object rawRecipeResourceLocation = FastNMS.INSTANCE.field$RecipeHolder$id(rawRecipeHolder);
|
||||||
|
Key rawRecipeKey = Key.of(rawRecipeResourceLocation.toString());
|
||||||
|
|
||||||
|
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
||||||
|
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(
|
||||||
|
injectedCacheCheck.recipeType() == MRecipeTypes.CAMPFIRE_COOKING ?
|
||||||
|
FastNMS.INSTANCE.field$SimpleContainer$items(args[0]).getFirst() :
|
||||||
|
FastNMS.INSTANCE.field$AbstractFurnaceBlockEntity$getItem(args[0], 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
boolean isCustom = recipeManager.isCustomRecipe(rawRecipeKey);
|
||||||
if (!isCustom) {
|
if (!isCustom) {
|
||||||
injectedCacheCheck.lastRecipe(id);
|
injectedCacheCheck.lastRecipe(rawRecipeResourceLocation);
|
||||||
return optionalRecipe;
|
return optionalRecipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,59 +192,45 @@ public class RecipeInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||||
CustomCookingRecipe<ItemStack> ceRecipe;
|
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe());
|
||||||
Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe();
|
|
||||||
if (type == MRecipeTypes.SMELTING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.BLASTING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.SMOKING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.CAMPFIRE_COOKING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input, lastCustomRecipe);
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
if (ceRecipe == null) {
|
if (ceRecipe == null) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache recipes, it might be incorrect on reloading
|
|
||||||
injectedCacheCheck.lastCustomRecipe(ceRecipe.id());
|
injectedCacheCheck.lastCustomRecipe(ceRecipe.id());
|
||||||
// It doesn't matter at all
|
if (!ceRecipe.id().equals(rawRecipeKey)) {
|
||||||
injectedCacheCheck.lastRecipe(id);
|
injectedCacheCheck.lastRecipe(KeyUtils.toResourceLocation(ceRecipe.id()));
|
||||||
return Optional.of(Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)).orElse(holder));
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
return Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public static class GetRecipeForMethodInterceptor1_21 {
|
public static class GetRecipeForMethodInterceptor1_21 {
|
||||||
public static final GetRecipeForMethodInterceptor1_21 INSTANCE = new GetRecipeForMethodInterceptor1_21();
|
public static final GetRecipeForMethodInterceptor1_21 INSTANCE = new GetRecipeForMethodInterceptor1_21();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@RuntimeType
|
@RuntimeType
|
||||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args) throws Exception {
|
public Object intercept(@This Object thisObj, @AllArguments Object[] args) {
|
||||||
Object mcRecipeManager = BukkitRecipeManager.nmsRecipeManager();
|
|
||||||
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
||||||
Object type = injectedCacheCheck.recipeType();
|
Object lastRecipeResourceLocation = injectedCacheCheck.lastRecipe();
|
||||||
Object lastRecipe = injectedCacheCheck.lastRecipe();
|
Optional<Object> optionalRecipe = (Optional<Object>) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.nmsRecipeManager(), injectedCacheCheck.recipeType(), args[0], args[1], lastRecipeResourceLocation);
|
||||||
Optional<Object> optionalRecipe = (Optional<Object>) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(mcRecipeManager, type, args[0], args[1], lastRecipe);
|
if (optionalRecipe.isEmpty()) {
|
||||||
if (optionalRecipe.isPresent()) {
|
return Optional.empty();
|
||||||
Object holder = optionalRecipe.get();
|
}
|
||||||
Object id = FastNMS.INSTANCE.field$RecipeHolder$id(holder);
|
|
||||||
Key recipeId = Key.of(id.toString());
|
|
||||||
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
|
||||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.field$SingleRecipeInput$item.get(args[0]));
|
|
||||||
|
|
||||||
// it's a recipe from other plugins
|
Object rawRecipeHolder = optionalRecipe.get();
|
||||||
boolean isCustom = recipeManager.isCustomRecipe(recipeId);
|
Object rawRecipeResourceLocation = FastNMS.INSTANCE.field$RecipeHolder$id(rawRecipeHolder);
|
||||||
|
Key rawRecipeKey = Key.of(rawRecipeResourceLocation.toString());
|
||||||
|
|
||||||
|
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
||||||
|
boolean isCustom = recipeManager.isCustomRecipe(rawRecipeKey);
|
||||||
if (!isCustom) {
|
if (!isCustom) {
|
||||||
injectedCacheCheck.lastRecipe(id);
|
injectedCacheCheck.lastRecipe(rawRecipeResourceLocation);
|
||||||
return optionalRecipe;
|
return optionalRecipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$SingleRecipeInput$item(args[0]));
|
||||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||||
if (idHolder.isEmpty()) {
|
if (idHolder.isEmpty()) {
|
||||||
@@ -252,60 +238,49 @@ public class RecipeInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||||
CustomCookingRecipe<ItemStack> ceRecipe;
|
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe());
|
||||||
Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe();
|
|
||||||
if (type == MRecipeTypes.SMELTING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.BLASTING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.SMOKING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.CAMPFIRE_COOKING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input, lastCustomRecipe);
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
if (ceRecipe == null) {
|
if (ceRecipe == null) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache recipes, it might be incorrect on reloading
|
|
||||||
injectedCacheCheck.lastCustomRecipe(ceRecipe.id());
|
injectedCacheCheck.lastCustomRecipe(ceRecipe.id());
|
||||||
// It doesn't matter at all
|
if (!ceRecipe.id().equals(rawRecipeKey)) {
|
||||||
injectedCacheCheck.lastRecipe(id);
|
injectedCacheCheck.lastRecipe(KeyUtils.toResourceLocation(ceRecipe.id()));
|
||||||
return Optional.of(Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)).orElse(holder));
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
return Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public static class GetRecipeForMethodInterceptor1_21_2 {
|
public static class GetRecipeForMethodInterceptor1_21_2 {
|
||||||
public static final GetRecipeForMethodInterceptor1_21_2 INSTANCE = new GetRecipeForMethodInterceptor1_21_2();
|
public static final GetRecipeForMethodInterceptor1_21_2 INSTANCE = new GetRecipeForMethodInterceptor1_21_2();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@RuntimeType
|
@RuntimeType
|
||||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args) throws Exception {
|
public Object intercept(@This Object thisObj, @AllArguments Object[] args) {
|
||||||
Object mcRecipeManager = BukkitRecipeManager.nmsRecipeManager();
|
|
||||||
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
||||||
Object type = injectedCacheCheck.recipeType();
|
Object lastRecipeResourceKey = injectedCacheCheck.lastRecipe();
|
||||||
Object lastRecipe = injectedCacheCheck.lastRecipe();
|
Optional<Object> optionalRecipe = (Optional<Object>) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.nmsRecipeManager(), injectedCacheCheck.recipeType(), args[0], args[1], lastRecipeResourceKey);
|
||||||
Optional<Object> optionalRecipe = (Optional<Object>) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(mcRecipeManager, type, args[0], args[1], lastRecipe);
|
if (optionalRecipe.isEmpty()) {
|
||||||
if (optionalRecipe.isPresent()) {
|
return Optional.empty();
|
||||||
Object holder = optionalRecipe.get();
|
}
|
||||||
Object id = FastNMS.INSTANCE.field$RecipeHolder$id(holder);
|
|
||||||
Object resourceLocation = FastNMS.INSTANCE.field$ResourceKey$location(id);
|
|
||||||
Key recipeId = Key.of(resourceLocation.toString());
|
|
||||||
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
|
||||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.field$SingleRecipeInput$item.get(args[0]));
|
|
||||||
|
|
||||||
// it's a recipe from other plugins
|
// 获取配方的基础信息
|
||||||
boolean isCustom = recipeManager.isCustomRecipe(recipeId);
|
Object recipeHolder = optionalRecipe.get();
|
||||||
|
Object rawRecipeResourceKey = FastNMS.INSTANCE.field$RecipeHolder$id(recipeHolder);
|
||||||
|
Object rawRecipeResourceLocation = FastNMS.INSTANCE.field$ResourceKey$location(rawRecipeResourceKey);
|
||||||
|
Key rawRecipeKey = Key.of(rawRecipeResourceLocation.toString());
|
||||||
|
|
||||||
|
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
||||||
|
// 来自其他插件注册的自定义配方
|
||||||
|
boolean isCustom = recipeManager.isCustomRecipe(rawRecipeKey);
|
||||||
if (!isCustom) {
|
if (!isCustom) {
|
||||||
injectedCacheCheck.lastRecipe(id);
|
injectedCacheCheck.lastRecipe(rawRecipeResourceKey);
|
||||||
return optionalRecipe;
|
return optionalRecipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取唯一内存地址id
|
||||||
|
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$SingleRecipeInput$item(args[0]));
|
||||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||||
if (idHolder.isEmpty()) {
|
if (idHolder.isEmpty()) {
|
||||||
@@ -313,29 +288,19 @@ public class RecipeInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||||
CustomCookingRecipe<ItemStack> ceRecipe;
|
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe());
|
||||||
Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe();
|
// 这个ce配方并不存在,那么应该返回空
|
||||||
if (type == MRecipeTypes.SMELTING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.BLASTING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe);
|
|
||||||
} else if (type == MRecipeTypes.SMOKING) {
|
|
||||||
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe);
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
if (ceRecipe == null) {
|
if (ceRecipe == null) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache recipes, it might be incorrect on reloading
|
// 记录上一次使用的配方(ce)
|
||||||
injectedCacheCheck.lastCustomRecipe(ceRecipe.id());
|
injectedCacheCheck.lastCustomRecipe(ceRecipe.id());
|
||||||
// It doesn't matter at all
|
// 更新上一次使用的配方(nms)
|
||||||
injectedCacheCheck.lastRecipe(id);
|
if (!ceRecipe.id().equals(rawRecipeKey)) {
|
||||||
return Optional.of(Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)).orElse(holder));
|
injectedCacheCheck.lastRecipe(FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.RECIPE, KeyUtils.toResourceLocation(ceRecipe.id())));
|
||||||
} else {
|
}
|
||||||
return Optional.empty();
|
return Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||||
|
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||||
import net.momirealms.craftengine.core.block.EmptyBlock;
|
import net.momirealms.craftengine.core.block.EmptyBlock;
|
||||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
@@ -220,23 +221,36 @@ public class WorldStorageInjector {
|
|||||||
CESection section = holder.ceSection();
|
CESection section = holder.ceSection();
|
||||||
// 如果是原版方块
|
// 如果是原版方块
|
||||||
if (BlockStateUtils.isVanillaBlock(stateId)) {
|
if (BlockStateUtils.isVanillaBlock(stateId)) {
|
||||||
// 那么应该情况自定义块
|
// 那么应该清空自定义块
|
||||||
ImmutableBlockState previous = section.setBlockState(x, y, z, EmptyBlock.STATE);
|
ImmutableBlockState previous = section.setBlockState(x, y, z, EmptyBlock.STATE);
|
||||||
// 如果先前不是空气则标记
|
// 处理 自定义块 -> 原版块
|
||||||
if (!previous.isEmpty()) {
|
if (!previous.isEmpty()) {
|
||||||
holder.ceChunk().setDirty(true);
|
holder.ceChunk().setDirty(true);
|
||||||
if (Config.enableLightSystem()) {
|
if (Config.enableLightSystem()) {
|
||||||
updateLightIfChanged(holder, previousState, newState, newState, x, y, z);
|
// 自定义块到原版块,只需要判断旧块是否和客户端一直
|
||||||
|
BlockStateWrapper wrapper = previous.vanillaBlockState();
|
||||||
|
if (wrapper != null) {
|
||||||
|
updateLight(holder, wrapper.handle(), previousState, x, y, z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
|
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
|
||||||
ImmutableBlockState previousImmutableBlockState = section.setBlockState(x, y, z, immutableBlockState);
|
ImmutableBlockState previousImmutableBlockState = section.setBlockState(x, y, z, immutableBlockState);
|
||||||
if (previousImmutableBlockState == immutableBlockState) return;
|
if (previousImmutableBlockState == immutableBlockState) return;
|
||||||
|
// 处理 自定义块到自定义块或原版块到自定义块
|
||||||
holder.ceChunk().setDirty(true);
|
holder.ceChunk().setDirty(true);
|
||||||
|
// 不可能!绝对不可能!
|
||||||
|
if (immutableBlockState.isEmpty()) return;
|
||||||
// 如果新方块的光照属性和客户端认为的不同
|
// 如果新方块的光照属性和客户端认为的不同
|
||||||
if (Config.enableLightSystem() && !immutableBlockState.isEmpty()) {
|
if (Config.enableLightSystem()) {
|
||||||
updateLightIfChanged(holder, previousState, immutableBlockState.vanillaBlockState().handle(), newState, x, y, z);
|
if (previousImmutableBlockState.isEmpty()) {
|
||||||
|
// 原版块到自定义块,只需要判断新块是否和客户端视觉一致
|
||||||
|
updateLight(holder, immutableBlockState.vanillaBlockState().handle(), newState, x, y, z);
|
||||||
|
} else {
|
||||||
|
// 自定义块到自定义块
|
||||||
|
updateLight$complex(holder, immutableBlockState.vanillaBlockState().handle(), newState, previousState, x, y, z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -244,17 +258,31 @@ public class WorldStorageInjector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void updateLightIfChanged(@This InjectedHolder thisObj, Object oldServerSideState, Object clientSideState, Object serverSideState, int x, int y, int z) {
|
@SuppressWarnings("DuplicatedCode")
|
||||||
|
protected static void updateLight(@This InjectedHolder thisObj, Object clientState, Object serverState, int x, int y, int z) {
|
||||||
CEWorld world = thisObj.ceChunk().world();
|
CEWorld world = thisObj.ceChunk().world();
|
||||||
Object blockPos = LocationUtils.toBlockPos(x, y, z);
|
Object blockPos = LocationUtils.toBlockPos(x, y, z);
|
||||||
Object serverWorld = world.world().serverWorld();
|
Object serverWorld = world.world().serverWorld();
|
||||||
if (clientSideState != serverSideState && FastNMS.INSTANCE.method$LightEngine$hasDifferentLightProperties(clientSideState, serverSideState, serverWorld, blockPos)) {
|
if (FastNMS.INSTANCE.method$LightEngine$hasDifferentLightProperties(serverState, clientState, serverWorld, blockPos)) {
|
||||||
|
SectionPos sectionPos = thisObj.cePos();
|
||||||
|
List<SectionPos> pos = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, 15);
|
||||||
|
world.sectionLightUpdated(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
|
protected static void updateLight$complex(@This InjectedHolder thisObj, Object newClientState, Object newServerState, Object oldServerState, int x, int y, int z) {
|
||||||
|
CEWorld world = thisObj.ceChunk().world();
|
||||||
|
Object blockPos = LocationUtils.toBlockPos(x, y, z);
|
||||||
|
Object serverWorld = world.world().serverWorld();
|
||||||
|
// 如果客户端新状态和服务端新状态光照属性不同
|
||||||
|
if (FastNMS.INSTANCE.method$LightEngine$hasDifferentLightProperties(newClientState, newServerState, serverWorld, blockPos)) {
|
||||||
SectionPos sectionPos = thisObj.cePos();
|
SectionPos sectionPos = thisObj.cePos();
|
||||||
List<SectionPos> pos = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, 15);
|
List<SectionPos> pos = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, 15);
|
||||||
world.sectionLightUpdated(pos);
|
world.sectionLightUpdated(pos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (FastNMS.INSTANCE.method$LightEngine$hasDifferentLightProperties(oldServerSideState, serverSideState, serverWorld, blockPos)) {
|
if (FastNMS.INSTANCE.method$LightEngine$hasDifferentLightProperties(newServerState, oldServerState, serverWorld, blockPos)) {
|
||||||
SectionPos sectionPos = thisObj.cePos();
|
SectionPos sectionPos = thisObj.cePos();
|
||||||
List<SectionPos> pos = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, 15);
|
List<SectionPos> pos = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, 15);
|
||||||
world.sectionLightUpdated(pos);
|
world.sectionLightUpdated(pos);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
|
|
||||||
private static final String CONNECTION_HANDLER_NAME = "craftengine_connection_handler";
|
private static final String CONNECTION_HANDLER_NAME = "craftengine_connection_handler";
|
||||||
private static final String SERVER_CHANNEL_HANDLER_NAME = "craftengine_server_channel_handler";
|
private static final String SERVER_CHANNEL_HANDLER_NAME = "craftengine_server_channel_handler";
|
||||||
private static final String PLAYER_CHANNEL_HANDLER_NAME = "craftengine_player_packet_handler";
|
private static final String PLAYER_CHANNEL_HANDLER_NAME = "craftengine_player_channel_handler";
|
||||||
private static final String PACKET_ENCODER = "craftengine_encoder";
|
private static final String PACKET_ENCODER = "craftengine_encoder";
|
||||||
private static final String PACKET_DECODER = "craftengine_decoder";
|
private static final String PACKET_DECODER = "craftengine_decoder";
|
||||||
|
|
||||||
@@ -147,9 +147,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
registerNMSPacketConsumer(PacketConsumers.SET_CREATIVE_SLOT, NetworkReflections.clazz$ServerboundSetCreativeModeSlotPacket);
|
registerNMSPacketConsumer(PacketConsumers.SET_CREATIVE_SLOT, NetworkReflections.clazz$ServerboundSetCreativeModeSlotPacket);
|
||||||
registerNMSPacketConsumer(PacketConsumers.LOGIN, NetworkReflections.clazz$ClientboundLoginPacket);
|
registerNMSPacketConsumer(PacketConsumers.LOGIN, NetworkReflections.clazz$ClientboundLoginPacket);
|
||||||
registerNMSPacketConsumer(PacketConsumers.RESPAWN, NetworkReflections.clazz$ClientboundRespawnPacket);
|
registerNMSPacketConsumer(PacketConsumers.RESPAWN, NetworkReflections.clazz$ClientboundRespawnPacket);
|
||||||
registerNMSPacketConsumer(PacketConsumers.INTERACT_ENTITY, NetworkReflections.clazz$ServerboundInteractPacket);
|
|
||||||
registerNMSPacketConsumer(PacketConsumers.SYNC_ENTITY_POSITION, NetworkReflections.clazz$ClientboundEntityPositionSyncPacket);
|
registerNMSPacketConsumer(PacketConsumers.SYNC_ENTITY_POSITION, NetworkReflections.clazz$ClientboundEntityPositionSyncPacket);
|
||||||
registerNMSPacketConsumer(PacketConsumers.MOVE_POS_ENTITY, NetworkReflections.clazz$ClientboundMoveEntityPacket$Pos);
|
|
||||||
registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, NetworkReflections.clazz$ServerboundPickItemFromEntityPacket);
|
registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, NetworkReflections.clazz$ServerboundPickItemFromEntityPacket);
|
||||||
registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, NetworkReflections.clazz$ServerboundRenameItemPacket);
|
registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, NetworkReflections.clazz$ServerboundRenameItemPacket);
|
||||||
registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, NetworkReflections.clazz$ServerboundSignUpdatePacket);
|
registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, NetworkReflections.clazz$ServerboundSignUpdatePacket);
|
||||||
@@ -161,6 +159,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, NetworkReflections.clazz$ServerboundResourcePackPacket);
|
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, NetworkReflections.clazz$ServerboundResourcePackPacket);
|
||||||
registerNMSPacketConsumer(PacketConsumers.ENTITY_EVENT, NetworkReflections.clazz$ClientboundEntityEventPacket);
|
registerNMSPacketConsumer(PacketConsumers.ENTITY_EVENT, NetworkReflections.clazz$ClientboundEntityEventPacket);
|
||||||
registerNMSPacketConsumer(PacketConsumers.MOVE_POS_AND_ROTATE_ENTITY, NetworkReflections.clazz$ClientboundMoveEntityPacket$PosRot);
|
registerNMSPacketConsumer(PacketConsumers.MOVE_POS_AND_ROTATE_ENTITY, NetworkReflections.clazz$ClientboundMoveEntityPacket$PosRot);
|
||||||
|
registerNMSPacketConsumer(PacketConsumers.MOVE_POS_ENTITY, NetworkReflections.clazz$ClientboundMoveEntityPacket$Pos);
|
||||||
registerS2CByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket());
|
registerS2CByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket());
|
||||||
registerS2CByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
registerS2CByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
||||||
registerS2CByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
|
registerS2CByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
|
||||||
@@ -177,7 +176,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
registerS2CByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.SET_OBJECTIVE_1_20_3 : PacketConsumers.SET_OBJECTIVE_1_20, this.packetIds.clientboundSetObjectivePacket());
|
registerS2CByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.SET_OBJECTIVE_1_20_3 : PacketConsumers.SET_OBJECTIVE_1_20, this.packetIds.clientboundSetObjectivePacket());
|
||||||
registerS2CByteBufPacketConsumer(PacketConsumers.SET_SCORE_1_20_3, VersionHelper.isOrAbove1_20_3() ? this.packetIds.clientboundSetScorePacket() : -1);
|
registerS2CByteBufPacketConsumer(PacketConsumers.SET_SCORE_1_20_3, VersionHelper.isOrAbove1_20_3() ? this.packetIds.clientboundSetScorePacket() : -1);
|
||||||
registerS2CByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket());
|
registerS2CByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket());
|
||||||
registerS2CByteBufPacketConsumer(PacketConsumers.ADD_ENTITY_BYTEBUFFER, this.packetIds.clientboundAddEntityPacket());
|
registerS2CByteBufPacketConsumer(PacketConsumers.ADD_ENTITY, this.packetIds.clientboundAddEntityPacket());
|
||||||
registerS2CByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket());
|
registerS2CByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket());
|
||||||
registerS2CByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket());
|
registerS2CByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket());
|
||||||
registerS2CByteBufPacketConsumer(PacketConsumers.CONTAINER_SET_CONTENT, this.packetIds.clientboundContainerSetContentPacket());
|
registerS2CByteBufPacketConsumer(PacketConsumers.CONTAINER_SET_CONTENT, this.packetIds.clientboundContainerSetContentPacket());
|
||||||
@@ -187,6 +186,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
registerS2CByteBufPacketConsumer(PacketConsumers.SET_PLAYER_INVENTORY_1_21_2, this.packetIds.clientboundSetPlayerInventoryPacket());
|
registerS2CByteBufPacketConsumer(PacketConsumers.SET_PLAYER_INVENTORY_1_21_2, this.packetIds.clientboundSetPlayerInventoryPacket());
|
||||||
registerC2SByteBufPacketConsumer(PacketConsumers.SET_CREATIVE_MODE_SLOT, this.packetIds.serverboundSetCreativeModeSlotPacket());
|
registerC2SByteBufPacketConsumer(PacketConsumers.SET_CREATIVE_MODE_SLOT, this.packetIds.serverboundSetCreativeModeSlotPacket());
|
||||||
registerC2SByteBufPacketConsumer(PacketConsumers.CONTAINER_CLICK_1_20, this.packetIds.serverboundContainerClickPacket());
|
registerC2SByteBufPacketConsumer(PacketConsumers.CONTAINER_CLICK_1_20, this.packetIds.serverboundContainerClickPacket());
|
||||||
|
registerC2SByteBufPacketConsumer(PacketConsumers.INTERACT_ENTITY, this.packetIds.serverboundInteractPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BukkitNetworkManager instance() {
|
public static BukkitNetworkManager instance() {
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ import org.bukkit.util.RayTraceResult;
|
|||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
@@ -85,7 +84,7 @@ public class PacketConsumers {
|
|||||||
public static void initEntities(int registrySize) {
|
public static void initEntities(int registrySize) {
|
||||||
ADD_ENTITY_HANDLERS = new BukkitNetworkManager.Handlers[registrySize];
|
ADD_ENTITY_HANDLERS = new BukkitNetworkManager.Handlers[registrySize];
|
||||||
Arrays.fill(ADD_ENTITY_HANDLERS, BukkitNetworkManager.Handlers.DO_NOTHING);
|
Arrays.fill(ADD_ENTITY_HANDLERS, BukkitNetworkManager.Handlers.DO_NOTHING);
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$FALLING_BLOCK$registryId] = (user, event) -> {
|
ADD_ENTITY_HANDLERS[MEntityTypes.FALLING_BLOCK$registryId] = (user, event) -> {
|
||||||
FriendlyByteBuf buf = event.getBuffer();
|
FriendlyByteBuf buf = event.getBuffer();
|
||||||
int id = buf.readVarInt();
|
int id = buf.readVarInt();
|
||||||
UUID uuid = buf.readUUID();
|
UUID uuid = buf.readUUID();
|
||||||
@@ -122,28 +121,27 @@ public class PacketConsumers {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$BLOCK_DISPLAY$registryId] = simpleAddEntityHandler(BlockDisplayPacketHandler.INSTANCE);
|
ADD_ENTITY_HANDLERS[MEntityTypes.BLOCK_DISPLAY$registryId] = simpleAddEntityHandler(BlockDisplayPacketHandler.INSTANCE);
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$TEXT_DISPLAY$registryId] = simpleAddEntityHandler(TextDisplayPacketHandler.INSTANCE);
|
ADD_ENTITY_HANDLERS[MEntityTypes.TEXT_DISPLAY$registryId] = simpleAddEntityHandler(TextDisplayPacketHandler.INSTANCE);
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$ARMOR_STAND$registryId] = simpleAddEntityHandler(ArmorStandPacketHandler.INSTANCE);
|
ADD_ENTITY_HANDLERS[MEntityTypes.ARMOR_STAND$registryId] = simpleAddEntityHandler(ArmorStandPacketHandler.INSTANCE);
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$ITEM_DISPLAY$registryId] = simpleAddEntityHandler(ItemDisplayPacketHandler.INSTANCE);
|
ADD_ENTITY_HANDLERS[MEntityTypes.ITEM$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$ITEM$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
ADD_ENTITY_HANDLERS[MEntityTypes.ITEM_FRAME$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$ITEM_FRAME$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
ADD_ENTITY_HANDLERS[MEntityTypes.GLOW_ITEM_FRAME$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$GLOW_ITEM_FRAME$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
ADD_ENTITY_HANDLERS[MEntityTypes.FIREBALL$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$FIREBALL$registryId] = createOptionalCustomProjectileEntityHandler();
|
ADD_ENTITY_HANDLERS[MEntityTypes.EYE_OF_ENDER$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$EYE_OF_ENDER$registryId] = createOptionalCustomProjectileEntityHandler();
|
ADD_ENTITY_HANDLERS[MEntityTypes.FIREWORK_ROCKET$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$FIREWORK_ROCKET$registryId] = createOptionalCustomProjectileEntityHandler();
|
ADD_ENTITY_HANDLERS[MEntityTypes.SMALL_FIREBALL$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$SMALL_FIREBALL$registryId] = createOptionalCustomProjectileEntityHandler();
|
ADD_ENTITY_HANDLERS[MEntityTypes.EGG$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$EGG$registryId] = createOptionalCustomProjectileEntityHandler();
|
ADD_ENTITY_HANDLERS[MEntityTypes.ENDER_PEARL$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$ENDER_PEARL$registryId] = createOptionalCustomProjectileEntityHandler();
|
ADD_ENTITY_HANDLERS[MEntityTypes.EXPERIENCE_BOTTLE$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$EXPERIENCE_BOTTLE$registryId] = createOptionalCustomProjectileEntityHandler();
|
ADD_ENTITY_HANDLERS[MEntityTypes.SNOWBALL$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$SNOWBALL$registryId] = createOptionalCustomProjectileEntityHandler();
|
ADD_ENTITY_HANDLERS[MEntityTypes.POTION$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$POTION$registryId] = createOptionalCustomProjectileEntityHandler();
|
ADD_ENTITY_HANDLERS[MEntityTypes.TRIDENT$registryId] = createOptionalCustomProjectileEntityHandler();
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$TRIDENT$registryId] = createOptionalCustomProjectileEntityHandler();
|
|
||||||
if (VersionHelper.isOrAbove1_20_5()) {
|
if (VersionHelper.isOrAbove1_20_5()) {
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$OMINOUS_ITEM_SPAWNER$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
ADD_ENTITY_HANDLERS[MEntityTypes.OMINOUS_ITEM_SPAWNER$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$ITEM_DISPLAY$registryId] = (user, event) -> {
|
ADD_ENTITY_HANDLERS[MEntityTypes.ITEM_DISPLAY$registryId] = (user, event) -> {
|
||||||
FriendlyByteBuf buf = event.getBuffer();
|
FriendlyByteBuf buf = event.getBuffer();
|
||||||
int id = buf.readVarInt();
|
int id = buf.readVarInt();
|
||||||
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(id);
|
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(id);
|
||||||
@@ -153,10 +151,12 @@ public class PacketConsumers {
|
|||||||
if (Config.hideBaseEntity() && !furniture.hasExternalModel()) {
|
if (Config.hideBaseEntity() && !furniture.hasExternalModel()) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
user.entityPacketHandlers().put(id, ItemDisplayPacketHandler.INSTANCE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$INTERACTION$registryId] = (user, event) -> {
|
ADD_ENTITY_HANDLERS[MEntityTypes.INTERACTION$registryId] = (user, event) -> {
|
||||||
if (BukkitFurnitureManager.NMS_COLLISION_ENTITY_TYPE != MEntityTypes.instance$EntityType$INTERACTION) return;
|
if (BukkitFurnitureManager.NMS_COLLISION_ENTITY_TYPE != MEntityTypes.INTERACTION) return;
|
||||||
FriendlyByteBuf buf = event.getBuffer();
|
FriendlyByteBuf buf = event.getBuffer();
|
||||||
int id = buf.readVarInt();
|
int id = buf.readVarInt();
|
||||||
// Cancel collider entity packet
|
// Cancel collider entity packet
|
||||||
@@ -166,8 +166,8 @@ public class PacketConsumers {
|
|||||||
user.entityPacketHandlers().put(id, FurnitureCollisionPacketHandler.INSTANCE);
|
user.entityPacketHandlers().put(id, FurnitureCollisionPacketHandler.INSTANCE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ADD_ENTITY_HANDLERS[MEntityTypes.instance$EntityType$OAK_BOAT$registryId] = (user, event) -> {
|
ADD_ENTITY_HANDLERS[MEntityTypes.OAK_BOAT$registryId] = (user, event) -> {
|
||||||
if (BukkitFurnitureManager.NMS_COLLISION_ENTITY_TYPE != MEntityTypes.instance$EntityType$OAK_BOAT) return;
|
if (BukkitFurnitureManager.NMS_COLLISION_ENTITY_TYPE != MEntityTypes.OAK_BOAT) return;
|
||||||
FriendlyByteBuf buf = event.getBuffer();
|
FriendlyByteBuf buf = event.getBuffer();
|
||||||
int id = buf.readVarInt();
|
int id = buf.readVarInt();
|
||||||
// Cancel collider entity packet
|
// Cancel collider entity packet
|
||||||
@@ -1106,13 +1106,13 @@ public class PacketConsumers {
|
|||||||
Object blockPos = FastNMS.INSTANCE.field$ServerboundPlayerActionPacket$pos(packet);
|
Object blockPos = FastNMS.INSTANCE.field$ServerboundPlayerActionPacket$pos(packet);
|
||||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||||
if (VersionHelper.isFolia()) {
|
if (VersionHelper.isFolia()) {
|
||||||
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
platformPlayer.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> {
|
||||||
try {
|
try {
|
||||||
handlePlayerActionPacketOnMainThread(player, world, pos, packet);
|
handlePlayerActionPacketOnMainThread(player, world, pos, packet);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPlayerActionPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundPlayerActionPacket", e);
|
||||||
}
|
}
|
||||||
}, world, pos.x() >> 4, pos.z() >> 4);
|
}, () -> {});
|
||||||
} else {
|
} else {
|
||||||
handlePlayerActionPacketOnMainThread(player, world, pos, packet);
|
handlePlayerActionPacketOnMainThread(player, world, pos, packet);
|
||||||
}
|
}
|
||||||
@@ -1172,21 +1172,21 @@ public class PacketConsumers {
|
|||||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HELLO_C2S = (user, event, packet) -> {
|
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HELLO_C2S = (user, event, packet) -> {
|
||||||
try {
|
try {
|
||||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||||
String name = (String) NetworkReflections.field$ServerboundHelloPacket$name.get(packet);
|
String name = (String) NetworkReflections.methodHandle$ServerboundHelloPacket$nameGetter.invokeExact(packet);
|
||||||
player.setName(name);
|
player.setName(name);
|
||||||
if (VersionHelper.isOrAbove1_20_2()) {
|
if (VersionHelper.isOrAbove1_20_2()) {
|
||||||
UUID uuid = (UUID) NetworkReflections.field$ServerboundHelloPacket$uuid.get(packet);
|
UUID uuid = (UUID) NetworkReflections.methodHandle$ServerboundHelloPacket$uuidGetter.invokeExact(packet);
|
||||||
player.setUUID(uuid);
|
player.setUUID(uuid);
|
||||||
} else {
|
} else {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Optional<UUID> uuid = (Optional<UUID>) NetworkReflections.field$ServerboundHelloPacket$uuid.get(packet);
|
Optional<UUID> uuid = (Optional<UUID>) NetworkReflections.methodHandle$ServerboundHelloPacket$uuidGetter.invokeExact(packet);
|
||||||
if (uuid.isPresent()) {
|
if (uuid.isPresent()) {
|
||||||
player.setUUID(uuid.get());
|
player.setUUID(uuid.get());
|
||||||
} else {
|
} else {
|
||||||
player.setUUID(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8)));
|
player.setUUID(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundHelloPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundHelloPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1223,10 +1223,10 @@ public class PacketConsumers {
|
|||||||
player.clearView();
|
player.clearView();
|
||||||
Object dimensionKey;
|
Object dimensionKey;
|
||||||
if (!VersionHelper.isOrAbove1_20_2()) {
|
if (!VersionHelper.isOrAbove1_20_2()) {
|
||||||
dimensionKey = NetworkReflections.field$ClientboundRespawnPacket$dimension.get(packet);
|
dimensionKey = NetworkReflections.methodHandle$ClientboundRespawnPacket$dimensionGetter.invokeExact(packet);
|
||||||
} else {
|
} else {
|
||||||
Object commonInfo = NetworkReflections.field$ClientboundRespawnPacket$commonPlayerSpawnInfo.get(packet);
|
Object commonInfo = NetworkReflections.methodHandle$ClientboundRespawnPacket$commonPlayerSpawnInfoGetter.invokeExact(packet);
|
||||||
dimensionKey = NetworkReflections.field$CommonPlayerSpawnInfo$dimension.get(commonInfo);
|
dimensionKey = NetworkReflections.methodHandle$CommonPlayerSpawnInfo$dimensionGetter.invokeExact(commonInfo);
|
||||||
}
|
}
|
||||||
Object location = FastNMS.INSTANCE.field$ResourceKey$location(dimensionKey);
|
Object location = FastNMS.INSTANCE.field$ResourceKey$location(dimensionKey);
|
||||||
World world = Bukkit.getWorld(Objects.requireNonNull(NamespacedKey.fromString(location.toString())));
|
World world = Bukkit.getWorld(Objects.requireNonNull(NamespacedKey.fromString(location.toString())));
|
||||||
@@ -1237,7 +1237,7 @@ public class PacketConsumers {
|
|||||||
} else {
|
} else {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundRespawnPacket: World " + location + " does not exist");
|
CraftEngine.instance().logger().warn("Failed to handle ClientboundRespawnPacket: World " + location + " does not exist");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundRespawnPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ClientboundRespawnPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1251,10 +1251,10 @@ public class PacketConsumers {
|
|||||||
if (BukkitNetworkManager.hasViaVersion()) {
|
if (BukkitNetworkManager.hasViaVersion()) {
|
||||||
user.setProtocolVersion(CraftEngine.instance().compatibilityManager().getPlayerProtocolVersion(player.uuid()));
|
user.setProtocolVersion(CraftEngine.instance().compatibilityManager().getPlayerProtocolVersion(player.uuid()));
|
||||||
}
|
}
|
||||||
dimensionKey = NetworkReflections.field$ClientboundLoginPacket$dimension.get(packet);
|
dimensionKey = NetworkReflections.methodHandle$ClientboundLoginPacket$dimensionGetter.invokeExact(packet);
|
||||||
} else {
|
} else {
|
||||||
Object commonInfo = NetworkReflections.field$ClientboundLoginPacket$commonPlayerSpawnInfo.get(packet);
|
Object commonInfo = NetworkReflections.methodHandle$ClientboundLoginPacket$commonPlayerSpawnInfoGetter.invokeExact(packet);
|
||||||
dimensionKey = NetworkReflections.field$CommonPlayerSpawnInfo$dimension.get(commonInfo);
|
dimensionKey = NetworkReflections.methodHandle$CommonPlayerSpawnInfo$dimensionGetter.invokeExact(commonInfo);
|
||||||
}
|
}
|
||||||
Object location = FastNMS.INSTANCE.field$ResourceKey$location(dimensionKey);
|
Object location = FastNMS.INSTANCE.field$ResourceKey$location(dimensionKey);
|
||||||
World world = Bukkit.getWorld(Objects.requireNonNull(NamespacedKey.fromString(location.toString())));
|
World world = Bukkit.getWorld(Objects.requireNonNull(NamespacedKey.fromString(location.toString())));
|
||||||
@@ -1265,7 +1265,7 @@ public class PacketConsumers {
|
|||||||
} else {
|
} else {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundLoginPacket: World " + location + " does not exist");
|
CraftEngine.instance().logger().warn("Failed to handle ClientboundLoginPacket: World " + location + " does not exist");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundLoginPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ClientboundLoginPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1282,25 +1282,25 @@ public class PacketConsumers {
|
|||||||
player.platformPlayer().getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> {
|
player.platformPlayer().getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> {
|
||||||
try {
|
try {
|
||||||
handleSetCreativeSlotPacketOnMainThread(player, packet);
|
handleSetCreativeSlotPacketOnMainThread(player, packet);
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e);
|
||||||
}
|
}
|
||||||
}, () -> {});
|
}, () -> {});
|
||||||
} else {
|
} else {
|
||||||
handleSetCreativeSlotPacketOnMainThread(player, packet);
|
handleSetCreativeSlotPacketOnMainThread(player, packet);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void handleSetCreativeSlotPacketOnMainThread(BukkitServerPlayer player, Object packet) throws Exception {
|
private static void handleSetCreativeSlotPacketOnMainThread(BukkitServerPlayer player, Object packet) throws Throwable {
|
||||||
Player bukkitPlayer = player.platformPlayer();
|
Player bukkitPlayer = player.platformPlayer();
|
||||||
if (bukkitPlayer == null) return;
|
if (bukkitPlayer == null) return;
|
||||||
if (bukkitPlayer.getGameMode() != GameMode.CREATIVE) return;
|
if (bukkitPlayer.getGameMode() != GameMode.CREATIVE) return;
|
||||||
int slot = VersionHelper.isOrAbove1_20_5() ? NetworkReflections.field$ServerboundSetCreativeModeSlotPacket$slotNum.getShort(packet) : NetworkReflections.field$ServerboundSetCreativeModeSlotPacket$slotNum.getInt(packet);
|
int slot = VersionHelper.isOrAbove1_20_5() ? (short) NetworkReflections.methodHandle$ServerboundSetCreativeModeSlotPacket$slotNumGetter.invokeExact(packet) : (int) NetworkReflections.methodHandle$ServerboundSetCreativeModeSlotPacket$slotNumGetter.invokeExact(packet);
|
||||||
if (slot < 36 || slot > 44) return;
|
if (slot < 36 || slot > 44) return;
|
||||||
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(NetworkReflections.field$ServerboundSetCreativeModeSlotPacket$itemStack.get(packet));
|
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(NetworkReflections.methodHandle$ServerboundSetCreativeModeSlotPacket$itemStackGetter.invokeExact(packet));
|
||||||
if (ItemUtils.isEmpty(item)) return;
|
if (ItemUtils.isEmpty(item)) return;
|
||||||
if (slot - 36 != bukkitPlayer.getInventory().getHeldItemSlot()) {
|
if (slot - 36 != bukkitPlayer.getInventory().getHeldItemSlot()) {
|
||||||
return;
|
return;
|
||||||
@@ -1373,14 +1373,14 @@ public class PacketConsumers {
|
|||||||
if (!user.isOnline()) return;
|
if (!user.isOnline()) return;
|
||||||
Player player = (Player) user.platformPlayer();
|
Player player = (Player) user.platformPlayer();
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
Object pos = NetworkReflections.field$ServerboundPickItemFromBlockPacket$pos.get(packet);
|
Object pos = NetworkReflections.methodHandle$ServerboundPickItemFromBlockPacket$posGetter.invokeExact(packet);
|
||||||
if (VersionHelper.isFolia()) {
|
if (VersionHelper.isFolia()) {
|
||||||
int x = FastNMS.INSTANCE.field$Vec3i$x(pos);
|
int x = FastNMS.INSTANCE.field$Vec3i$x(pos);
|
||||||
int z = FastNMS.INSTANCE.field$Vec3i$z(pos);
|
int z = FastNMS.INSTANCE.field$Vec3i$z(pos);
|
||||||
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
||||||
try {
|
try {
|
||||||
handlePickItemFromBlockPacketOnMainThread(player, pos);
|
handlePickItemFromBlockPacketOnMainThread(player, pos);
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e);
|
||||||
}
|
}
|
||||||
}, player.getWorld(), x >> 4, z >> 4);
|
}, player.getWorld(), x >> 4, z >> 4);
|
||||||
@@ -1388,17 +1388,17 @@ public class PacketConsumers {
|
|||||||
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
||||||
try {
|
try {
|
||||||
handlePickItemFromBlockPacketOnMainThread(player, pos);
|
handlePickItemFromBlockPacketOnMainThread(player, pos);
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void handlePickItemFromBlockPacketOnMainThread(Player player, Object pos) throws Exception {
|
private static void handlePickItemFromBlockPacketOnMainThread(Player player, Object pos) throws Throwable {
|
||||||
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(player.getWorld());
|
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(player.getWorld());
|
||||||
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(serverLevel, pos);
|
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(serverLevel, pos);
|
||||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||||
@@ -1411,7 +1411,7 @@ public class PacketConsumers {
|
|||||||
// 1.21.4+
|
// 1.21.4+
|
||||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> PICK_ITEM_FROM_ENTITY = (user, event, packet) -> {
|
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> PICK_ITEM_FROM_ENTITY = (user, event, packet) -> {
|
||||||
try {
|
try {
|
||||||
int entityId = (int) NetworkReflections.field$ServerboundPickItemFromEntityPacket$id.get(packet);
|
int entityId = (int) NetworkReflections.methodHandle$ServerboundPickItemFromEntityPacket$idGetter.invokeExact(packet);
|
||||||
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
|
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
|
||||||
if (furniture == null) return;
|
if (furniture == null) return;
|
||||||
Player player = (Player) user.platformPlayer();
|
Player player = (Player) user.platformPlayer();
|
||||||
@@ -1420,7 +1420,7 @@ public class PacketConsumers {
|
|||||||
player.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> {
|
player.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> {
|
||||||
try {
|
try {
|
||||||
handlePickItemFromEntityOnMainThread(player, furniture);
|
handlePickItemFromEntityOnMainThread(player, furniture);
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
|
||||||
}
|
}
|
||||||
}, () -> {});
|
}, () -> {});
|
||||||
@@ -1428,23 +1428,23 @@ public class PacketConsumers {
|
|||||||
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
||||||
try {
|
try {
|
||||||
handlePickItemFromEntityOnMainThread(player, furniture);
|
handlePickItemFromEntityOnMainThread(player, furniture);
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void handlePickItemFromEntityOnMainThread(Player player, BukkitFurniture furniture) throws Exception {
|
private static void handlePickItemFromEntityOnMainThread(Player player, BukkitFurniture furniture) throws Throwable {
|
||||||
Key itemId = furniture.config().settings().itemId();
|
Key itemId = furniture.config().settings().itemId();
|
||||||
if (itemId == null) return;
|
if (itemId == null) return;
|
||||||
pickItem(player, itemId, null, FastNMS.INSTANCE.method$CraftEntity$getHandle(furniture.baseEntity()));
|
pickItem(player, itemId, null, FastNMS.INSTANCE.method$CraftEntity$getHandle(furniture.baseEntity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void pickItem(Player player, Key itemId, @Nullable Object blockPos, @Nullable Object entity) throws IllegalAccessException, InvocationTargetException {
|
private static void pickItem(Player player, Key itemId, @Nullable Object blockPos, @Nullable Object entity) throws Throwable {
|
||||||
ItemStack itemStack = BukkitCraftEngine.instance().itemManager().buildCustomItemStack(itemId, BukkitCraftEngine.instance().adapt(player));
|
ItemStack itemStack = BukkitCraftEngine.instance().itemManager().buildCustomItemStack(itemId, BukkitCraftEngine.instance().adapt(player));
|
||||||
if (itemStack == null) {
|
if (itemStack == null) {
|
||||||
CraftEngine.instance().logger().warn("Item: " + itemId + " is not a valid item");
|
CraftEngine.instance().logger().warn("Item: " + itemId + " is not a valid item");
|
||||||
@@ -1453,15 +1453,15 @@ public class PacketConsumers {
|
|||||||
assert CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem != null;
|
assert CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem != null;
|
||||||
if (VersionHelper.isOrAbove1_21_5()) {
|
if (VersionHelper.isOrAbove1_21_5()) {
|
||||||
CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke(
|
CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke(
|
||||||
CoreReflections.field$ServerPlayer$connection.get(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)),
|
CoreReflections.methodHandle$ServerPlayer$connectionGetter.invokeExact(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)),
|
||||||
FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack), blockPos, entity, true);
|
FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack), blockPos, entity, true);
|
||||||
} else {
|
} else {
|
||||||
CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke(
|
CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke(
|
||||||
CoreReflections.field$ServerPlayer$connection.get(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)), FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack));
|
CoreReflections.methodHandle$ServerPlayer$connectionGetter.invokeExact(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)), FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> ADD_ENTITY_BYTEBUFFER = (user, event) -> {
|
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> ADD_ENTITY = (user, event) -> {
|
||||||
try {
|
try {
|
||||||
FriendlyByteBuf buf = event.getBuffer();
|
FriendlyByteBuf buf = event.getBuffer();
|
||||||
buf.readVarInt();
|
buf.readVarInt();
|
||||||
@@ -1509,83 +1509,108 @@ public class PacketConsumers {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> INTERACT_ENTITY = (user, event, packet) -> {
|
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> INTERACT_ENTITY = (user, event) -> {
|
||||||
try {
|
try {
|
||||||
Player player = (Player) user.platformPlayer();
|
FriendlyByteBuf buf = event.getBuffer();
|
||||||
if (player == null) return;
|
int entityId = BukkitNetworkManager.hasModelEngine() ?
|
||||||
int entityId;
|
CraftEngine.instance().compatibilityManager().interactionToBaseEntity(buf.readVarInt()) :
|
||||||
if (BukkitNetworkManager.hasModelEngine()) {
|
buf.readVarInt();
|
||||||
int fakeId = FastNMS.INSTANCE.field$ServerboundInteractPacket$entityId(packet);
|
|
||||||
entityId = CraftEngine.instance().compatibilityManager().interactionToBaseEntity(fakeId);
|
|
||||||
} else {
|
|
||||||
entityId = FastNMS.INSTANCE.field$ServerboundInteractPacket$entityId(packet);
|
|
||||||
}
|
|
||||||
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
|
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
|
||||||
if (furniture == null) return;
|
if (furniture == null) return;
|
||||||
Object action = NetworkReflections.field$ServerboundInteractPacket$action.get(packet);
|
int actionType = buf.readVarInt();
|
||||||
Object actionType = NetworkReflections.method$ServerboundInteractPacket$Action$getType.invoke(action);
|
|
||||||
if (actionType == null) return;
|
|
||||||
Location location = furniture.baseEntity().getLocation();
|
|
||||||
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user;
|
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user;
|
||||||
if (serverPlayer.isSpectatorMode()) return;
|
if (serverPlayer.isSpectatorMode()) return;
|
||||||
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
Player platformPlayer = serverPlayer.platformPlayer();
|
||||||
if (actionType == NetworkReflections.instance$ServerboundInteractPacket$ActionType$ATTACK) {
|
Location location = furniture.baseEntity().getLocation();
|
||||||
// todo 冒险模式破坏工具白名单
|
|
||||||
if (serverPlayer.isAdventureMode()) return;
|
Runnable mainThreadTask;
|
||||||
if (furniture.isValid()) {
|
if (actionType == 1) {
|
||||||
if (!BukkitCraftEngine.instance().antiGrief().canBreak(player, location)) {
|
// ATTACK
|
||||||
return;
|
boolean usingSecondaryAction = buf.readBoolean();
|
||||||
}
|
if (entityId != furniture.baseEntityId()) {
|
||||||
FurnitureBreakEvent breakEvent = new FurnitureBreakEvent(serverPlayer.platformPlayer(), furniture);
|
event.setChanged(true);
|
||||||
if (EventUtils.fireAndCheckCancel(breakEvent)) {
|
buf.clear();
|
||||||
return;
|
buf.writeVarInt(event.packetID());
|
||||||
|
buf.writeVarInt(furniture.baseEntityId());
|
||||||
|
buf.writeVarInt(actionType);
|
||||||
|
buf.writeBoolean(usingSecondaryAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainThreadTask = () -> {
|
||||||
|
// todo 冒险模式破坏工具白名单
|
||||||
|
if (serverPlayer.isAdventureMode() ||
|
||||||
|
!furniture.isValid() ||
|
||||||
|
!BukkitCraftEngine.instance().antiGrief().canBreak(platformPlayer, location)
|
||||||
|
) return;
|
||||||
|
|
||||||
|
FurnitureBreakEvent breakEvent = new FurnitureBreakEvent(serverPlayer.platformPlayer(), furniture);
|
||||||
|
if (EventUtils.fireAndCheckCancel(breakEvent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Cancellable cancellable = Cancellable.of(breakEvent::isCancelled, breakEvent::setCancelled);
|
||||||
// execute functions
|
// execute functions
|
||||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||||
.withParameter(DirectContextParameters.FURNITURE, furniture)
|
.withParameter(DirectContextParameters.FURNITURE, furniture)
|
||||||
|
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||||
|
.withParameter(DirectContextParameters.HAND, InteractionHand.MAIN_HAND)
|
||||||
|
.withParameter(DirectContextParameters.ITEM_IN_HAND, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND))
|
||||||
.withParameter(DirectContextParameters.POSITION, furniture.position())
|
.withParameter(DirectContextParameters.POSITION, furniture.position())
|
||||||
);
|
);
|
||||||
furniture.config().execute(context, EventTrigger.LEFT_CLICK);
|
furniture.config().execute(context, EventTrigger.LEFT_CLICK);
|
||||||
furniture.config().execute(context, EventTrigger.BREAK);
|
furniture.config().execute(context, EventTrigger.BREAK);
|
||||||
|
if (cancellable.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CraftEngineFurniture.remove(furniture, serverPlayer, !serverPlayer.isCreativeMode(), true);
|
CraftEngineFurniture.remove(furniture, serverPlayer, !serverPlayer.isCreativeMode(), true);
|
||||||
|
};
|
||||||
|
} else if (actionType == 2) {
|
||||||
|
// INTERACT_AT
|
||||||
|
float x = buf.readFloat();
|
||||||
|
float y = buf.readFloat();
|
||||||
|
float z = buf.readFloat();
|
||||||
|
Location interactionPoint = new Location(platformPlayer.getWorld(), x, y, z);
|
||||||
|
InteractionHand hand = buf.readVarInt() == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||||
|
boolean usingSecondaryAction = buf.readBoolean();
|
||||||
|
if (entityId != furniture.baseEntityId()) {
|
||||||
|
event.setChanged(true);
|
||||||
|
buf.clear();
|
||||||
|
buf.writeVarInt(event.packetID());
|
||||||
|
buf.writeVarInt(furniture.baseEntityId());
|
||||||
|
buf.writeVarInt(actionType);
|
||||||
|
buf.writeFloat(x).writeFloat(y).writeFloat(z);
|
||||||
|
buf.writeVarInt(hand == InteractionHand.MAIN_HAND ? 0 : 1);
|
||||||
|
buf.writeBoolean(usingSecondaryAction);
|
||||||
}
|
}
|
||||||
} else if (actionType == NetworkReflections.instance$ServerboundInteractPacket$ActionType$INTERACT_AT) {
|
|
||||||
InteractionHand hand;
|
|
||||||
Location interactionPoint;
|
|
||||||
try {
|
|
||||||
Object interactionHand = NetworkReflections.field$ServerboundInteractPacket$InteractionAtLocationAction$hand.get(action);
|
|
||||||
hand = interactionHand == CoreReflections.instance$InteractionHand$MAIN_HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
|
||||||
Object vec3 = NetworkReflections.field$ServerboundInteractPacket$InteractionAtLocationAction$location.get(action);
|
|
||||||
|
|
||||||
double x = FastNMS.INSTANCE.field$Vec3$x(vec3);
|
mainThreadTask = () -> {
|
||||||
double y = FastNMS.INSTANCE.field$Vec3$y(vec3);
|
|
||||||
double z = FastNMS.INSTANCE.field$Vec3$z(vec3);
|
|
||||||
interactionPoint = new Location(location.getWorld(), x, y, z);
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
throw new RuntimeException("Failed to get interaction hand from interact packet", e);
|
|
||||||
}
|
|
||||||
FurnitureInteractEvent interactEvent = new FurnitureInteractEvent(serverPlayer.platformPlayer(), furniture, hand, interactionPoint);
|
FurnitureInteractEvent interactEvent = new FurnitureInteractEvent(serverPlayer.platformPlayer(), furniture, hand, interactionPoint);
|
||||||
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||||
|
Cancellable cancellable = Cancellable.of(interactEvent::isCancelled, interactEvent::setCancelled);
|
||||||
// execute functions
|
// execute functions
|
||||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||||
|
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||||
.withParameter(DirectContextParameters.FURNITURE, furniture)
|
.withParameter(DirectContextParameters.FURNITURE, furniture)
|
||||||
|
.withParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
|
||||||
|
.withParameter(DirectContextParameters.HAND, hand)
|
||||||
.withParameter(DirectContextParameters.POSITION, furniture.position())
|
.withParameter(DirectContextParameters.POSITION, furniture.position())
|
||||||
);
|
);
|
||||||
furniture.config().execute(context, EventTrigger.RIGHT_CLICK);
|
furniture.config().execute(context, EventTrigger.RIGHT_CLICK);
|
||||||
|
if (cancellable.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (player.isSneaking()) {
|
// 必须从网络包层面处理,否则无法获取交互的具体实体
|
||||||
|
if (serverPlayer.isSecondaryUseActive() && itemInHand != null) {
|
||||||
// try placing another furniture above it
|
// try placing another furniture above it
|
||||||
AABB hitBox = furniture.aabbByEntityId(entityId);
|
AABB hitBox = furniture.aabbByEntityId(entityId);
|
||||||
if (hitBox == null) return;
|
if (hitBox == null) return;
|
||||||
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
||||||
if (itemInHand == null) return;
|
Location eyeLocation = platformPlayer.getEyeLocation();
|
||||||
Optional<CustomItem<ItemStack>> optionalCustomitem = itemInHand.getCustomItem();
|
|
||||||
Location eyeLocation = player.getEyeLocation();
|
|
||||||
Vector direction = eyeLocation.getDirection();
|
Vector direction = eyeLocation.getDirection();
|
||||||
Location endLocation = eyeLocation.clone();
|
Location endLocation = eyeLocation.clone();
|
||||||
endLocation.add(direction.multiply(serverPlayer.getCachedInteractionRange()));
|
endLocation.add(direction.multiply(serverPlayer.getCachedInteractionRange()));
|
||||||
@@ -1594,8 +1619,8 @@ public class PacketConsumers {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EntityHitResult hitResult = result.get();
|
EntityHitResult hitResult = result.get();
|
||||||
if (optionalCustomitem.isPresent() && !optionalCustomitem.get().behaviors().isEmpty()) {
|
if (optionalCustomItem.isPresent() && !optionalCustomItem.get().behaviors().isEmpty()) {
|
||||||
for (ItemBehavior behavior : optionalCustomitem.get().behaviors()) {
|
for (ItemBehavior behavior : optionalCustomItem.get().behaviors()) {
|
||||||
if (behavior instanceof FurnitureItemBehavior) {
|
if (behavior instanceof FurnitureItemBehavior) {
|
||||||
behavior.useOnBlock(new UseOnContext(serverPlayer, InteractionHand.MAIN_HAND, new BlockHitResult(hitResult.hitLocation(), hitResult.direction(), BlockPos.fromVec3d(hitResult.hitLocation()), false)));
|
behavior.useOnBlock(new UseOnContext(serverPlayer, InteractionHand.MAIN_HAND, new BlockHitResult(hitResult.hitLocation(), hitResult.direction(), BlockPos.fromVec3d(hitResult.hitLocation()), false)));
|
||||||
return;
|
return;
|
||||||
@@ -1604,7 +1629,12 @@ public class PacketConsumers {
|
|||||||
}
|
}
|
||||||
// now simulate vanilla item behavior
|
// now simulate vanilla item behavior
|
||||||
serverPlayer.setResendSound();
|
serverPlayer.setResendSound();
|
||||||
FastNMS.INSTANCE.simulateInteraction(serverPlayer.serverPlayer(), DirectionUtils.toNMSDirection(hitResult.direction()), hitResult.hitLocation().x, hitResult.hitLocation().y, hitResult.hitLocation().z, LocationUtils.toBlockPos(hitResult.blockPos()));
|
FastNMS.INSTANCE.simulateInteraction(
|
||||||
|
serverPlayer.serverPlayer(),
|
||||||
|
DirectionUtils.toNMSDirection(hitResult.direction()),
|
||||||
|
hitResult.hitLocation().x, hitResult.hitLocation().y, hitResult.hitLocation().z,
|
||||||
|
LocationUtils.toBlockPos(hitResult.blockPos())
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
furniture.findFirstAvailableSeat(entityId).ifPresent(seatPos -> {
|
furniture.findFirstAvailableSeat(entityId).ifPresent(seatPos -> {
|
||||||
if (furniture.tryOccupySeat(seatPos)) {
|
if (furniture.tryOccupySeat(seatPos)) {
|
||||||
@@ -1612,9 +1642,30 @@ public class PacketConsumers {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
} else if (actionType == 0) {
|
||||||
|
int hand = buf.readVarInt();
|
||||||
|
boolean usingSecondaryAction = buf.readBoolean();
|
||||||
|
if (entityId != furniture.baseEntityId()) {
|
||||||
|
event.setChanged(true);
|
||||||
|
buf.clear();
|
||||||
|
buf.writeVarInt(event.packetID());
|
||||||
|
buf.writeVarInt(furniture.baseEntityId());
|
||||||
|
buf.writeVarInt(actionType);
|
||||||
|
buf.writeVarInt(hand);
|
||||||
|
buf.writeBoolean(usingSecondaryAction);
|
||||||
}
|
}
|
||||||
}, player.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
return;
|
||||||
} catch (Exception e) {
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VersionHelper.isFolia()) {
|
||||||
|
platformPlayer.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), t -> mainThreadTask.run(), () -> {});
|
||||||
|
} else {
|
||||||
|
BukkitCraftEngine.instance().scheduler().executeSync(mainThreadTask);
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundInteractPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundInteractPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1699,20 +1750,20 @@ public class PacketConsumers {
|
|||||||
if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_ANVIL)) {
|
if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_ANVIL)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String message = (String) NetworkReflections.field$ServerboundRenameItemPacket$name.get(packet);
|
String message = (String) NetworkReflections.methodHandle$ServerboundRenameItemPacket$nameGetter.invokeExact(packet);
|
||||||
if (message != null && !message.isEmpty()) {
|
if (message != null && !message.isEmpty()) {
|
||||||
// check bypass
|
// check bypass
|
||||||
FontManager manager = CraftEngine.instance().fontManager();
|
FontManager manager = CraftEngine.instance().fontManager();
|
||||||
IllegalCharacterProcessResult result = manager.processIllegalCharacters(message);
|
IllegalCharacterProcessResult result = manager.processIllegalCharacters(message);
|
||||||
if (result.has()) {
|
if (result.has()) {
|
||||||
try {
|
try {
|
||||||
NetworkReflections.field$ServerboundRenameItemPacket$name.set(packet, result.text());
|
NetworkReflections.methodHandle$ServerboundRenameItemPacket$nameSetter.invokeExact(packet, result.text());
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to replace chat", e);
|
CraftEngine.instance().logger().warn("Failed to replace chat", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundRenameItemPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundRenameItemPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1725,7 +1776,7 @@ public class PacketConsumers {
|
|||||||
if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_SIGN)) {
|
if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_SIGN)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String[] lines = (String[]) NetworkReflections.field$ServerboundSignUpdatePacket$lines.get(packet);
|
String[] lines = (String[]) NetworkReflections.methodHandle$ServerboundSignUpdatePacket$linesGetter.invokeExact(packet);
|
||||||
FontManager manager = CraftEngine.instance().fontManager();
|
FontManager manager = CraftEngine.instance().fontManager();
|
||||||
if (!manager.isDefaultFontInUse()) return;
|
if (!manager.isDefaultFontInUse()) return;
|
||||||
for (int i = 0; i < lines.length; i++) {
|
for (int i = 0; i < lines.length; i++) {
|
||||||
@@ -1737,7 +1788,7 @@ public class PacketConsumers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundSignUpdatePacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundSignUpdatePacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1756,9 +1807,9 @@ public class PacketConsumers {
|
|||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
List<String> pages = (List<String>) NetworkReflections.field$ServerboundEditBookPacket$pages.get(packet);
|
List<String> pages = (List<String>) NetworkReflections.methodHandle$ServerboundEditBookPacket$pagesGetter.invokeExact(packet);
|
||||||
List<String> newPages = new ArrayList<>(pages.size());
|
List<String> newPages = new ArrayList<>(pages.size());
|
||||||
Optional<String> title = (Optional<String>) NetworkReflections.field$ServerboundEditBookPacket$title.get(packet);
|
Optional<String> title = (Optional<String>) NetworkReflections.methodHandle$ServerboundEditBookPacket$titleGetter.invokeExact(packet);
|
||||||
Optional<String> newTitle;
|
Optional<String> newTitle;
|
||||||
|
|
||||||
if (title.isPresent()) {
|
if (title.isPresent()) {
|
||||||
@@ -1782,13 +1833,13 @@ public class PacketConsumers {
|
|||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
Object newPacket = NetworkReflections.constructor$ServerboundEditBookPacket.newInstance(
|
Object newPacket = NetworkReflections.constructor$ServerboundEditBookPacket.newInstance(
|
||||||
NetworkReflections.field$ServerboundEditBookPacket$slot.get(packet),
|
(int) NetworkReflections.methodHandle$ServerboundEditBookPacket$slotGetter.invokeExact(packet),
|
||||||
newPages,
|
newPages,
|
||||||
newTitle
|
newTitle
|
||||||
);
|
);
|
||||||
event.replacePacket(newPacket);
|
event.replacePacket(newPacket);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundEditBookPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundEditBookPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1815,7 +1866,7 @@ public class PacketConsumers {
|
|||||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> CUSTOM_PAYLOAD = (user, event, packet) -> {
|
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> CUSTOM_PAYLOAD = (user, event, packet) -> {
|
||||||
try {
|
try {
|
||||||
if (!VersionHelper.isOrAbove1_20_5()) return;
|
if (!VersionHelper.isOrAbove1_20_5()) return;
|
||||||
Object payload = NetworkReflections.field$ServerboundCustomPayloadPacket$payload.get(packet);
|
Object payload = NetworkReflections.methodHandle$ServerboundCustomPayloadPacket$payloadGetter.invokeExact(packet);
|
||||||
if (NetworkReflections.clazz$DiscardedPayload.isInstance(payload)) {
|
if (NetworkReflections.clazz$DiscardedPayload.isInstance(payload)) {
|
||||||
Payload discardedPayload = DiscardedPayload.from(payload);
|
Payload discardedPayload = DiscardedPayload.from(payload);
|
||||||
if (discardedPayload == null || !discardedPayload.channel().equals(NetworkManager.MOD_CHANNEL_KEY))
|
if (discardedPayload == null || !discardedPayload.channel().equals(NetworkManager.MOD_CHANNEL_KEY))
|
||||||
@@ -1844,7 +1895,7 @@ public class PacketConsumers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundCustomPayloadPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundCustomPayloadPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2234,9 +2285,9 @@ public class PacketConsumers {
|
|||||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HANDSHAKE_C2S = (user, event, packet) -> {
|
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HANDSHAKE_C2S = (user, event, packet) -> {
|
||||||
try {
|
try {
|
||||||
if (BukkitNetworkManager.hasViaVersion()) return;
|
if (BukkitNetworkManager.hasViaVersion()) return;
|
||||||
int protocolVersion = NetworkReflections.field$ClientIntentionPacket$protocolVersion.getInt(packet);
|
int protocolVersion = (int) NetworkReflections.methodHandle$ClientIntentionPacket$protocolVersionGetter.invokeExact(packet);
|
||||||
user.setProtocolVersion(protocolVersion);
|
user.setProtocolVersion(protocolVersion);
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ClientIntentionPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ClientIntentionPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2254,7 +2305,7 @@ public class PacketConsumers {
|
|||||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RESOURCE_PACK_RESPONSE = (user, event, packet) -> {
|
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RESOURCE_PACK_RESPONSE = (user, event, packet) -> {
|
||||||
try {
|
try {
|
||||||
if (user.sentResourcePack() || !Config.sendPackOnJoin() || !Config.kickOnDeclined()) return;
|
if (user.sentResourcePack() || !Config.sendPackOnJoin() || !Config.kickOnDeclined()) return;
|
||||||
Object action = NetworkReflections.field$ServerboundResourcePackPacket$action.get(packet);
|
Object action = NetworkReflections.methodHandle$ServerboundResourcePackPacket$actionGetter.invokeExact(packet);
|
||||||
if (action == null) return;
|
if (action == null) return;
|
||||||
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$DECLINED
|
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$DECLINED
|
||||||
|| action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$FAILED_DOWNLOAD) {
|
|| action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$FAILED_DOWNLOAD) {
|
||||||
@@ -2267,7 +2318,7 @@ public class PacketConsumers {
|
|||||||
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$SUCCESSFULLY_LOADED) {
|
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$SUCCESSFULLY_LOADED) {
|
||||||
user.setSentResourcePack(true);
|
user.setSentResourcePack(true);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundResourcePackPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ServerboundResourcePackPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2276,28 +2327,17 @@ public class PacketConsumers {
|
|||||||
try {
|
try {
|
||||||
Object player = user.serverPlayer();
|
Object player = user.serverPlayer();
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
int entityId = NetworkReflections.field$ClientboundEntityEventPacket$entityId.getInt(packet);
|
int entityId = (int) NetworkReflections.methodHandle$ClientboundEntityEventPacket$entityIdGetter.invokeExact(packet);
|
||||||
if (entityId != FastNMS.INSTANCE.method$Entity$getId(player)) return;
|
if (entityId != FastNMS.INSTANCE.method$Entity$getId(player)) return;
|
||||||
byte eventId = NetworkReflections.field$ClientboundEntityEventPacket$eventId.getByte(packet);
|
byte eventId = (byte) NetworkReflections.methodHandle$ClientboundEntityEventPacket$eventIdGetter.invokeExact(packet);
|
||||||
if (eventId >= 24 && eventId <= 28) {
|
if (eventId >= 24 && eventId <= 28) {
|
||||||
CraftEngine.instance().fontManager().refreshEmojiSuggestions(user.uuid());
|
CraftEngine.instance().fontManager().refreshEmojiSuggestions(user.uuid());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundEntityEventPacket", e);
|
CraftEngine.instance().logger().warn("Failed to handle ClientboundEntityEventPacket", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_POS_ENTITY = (user, event, packet) -> {
|
|
||||||
try {
|
|
||||||
int entityId = ProtectedFieldVisitor.get().field$ClientboundMoveEntityPacket$entityId(packet);
|
|
||||||
if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_POS_AND_ROTATE_ENTITY = (user, event, packet) -> {
|
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_POS_AND_ROTATE_ENTITY = (user, event, packet) -> {
|
||||||
try {
|
try {
|
||||||
int entityId = ProtectedFieldVisitor.get().field$ClientboundMoveEntityPacket$entityId(packet);
|
int entityId = ProtectedFieldVisitor.get().field$ClientboundMoveEntityPacket$entityId(packet);
|
||||||
@@ -2310,4 +2350,15 @@ public class PacketConsumers {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_POS_ENTITY = (user, event, packet) -> {
|
||||||
|
try {
|
||||||
|
int entityId = ProtectedFieldVisitor.get().field$ClientboundMoveEntityPacket$entityId(packet);
|
||||||
|
EntityPacketHandler handler = user.entityPacketHandlers().get(entityId);
|
||||||
|
if (handler != null) {
|
||||||
|
handler.handleMove(user, event, packet);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,11 @@ public interface PacketIds {
|
|||||||
|
|
||||||
int clientboundSetPlayerInventoryPacket();
|
int clientboundSetPlayerInventoryPacket();
|
||||||
|
|
||||||
|
int clientboundBlockEventPacket();
|
||||||
|
|
||||||
int serverboundContainerClickPacket();
|
int serverboundContainerClickPacket();
|
||||||
|
|
||||||
int serverboundSetCreativeModeSlotPacket();
|
int serverboundSetCreativeModeSlotPacket();
|
||||||
|
|
||||||
|
int serverboundInteractPacket();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||||
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
|
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
|
||||||
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||||
@@ -27,6 +29,11 @@ public class CommonItemPacketHandler implements EntityPacketHandler {
|
|||||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||||
if (entityDataId == EntityDataUtils.ITEM_DATA_ID) {
|
if (entityDataId == EntityDataUtils.ITEM_DATA_ID) {
|
||||||
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||||
|
// TODO 检查为什么会导致问题,难道是其他插件乱发entity id?
|
||||||
|
if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) {
|
||||||
|
CraftEngine.instance().logger().warn("Invalid item data for entity " + id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
|
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
|
||||||
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user);
|
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user);
|
||||||
if (optional.isPresent()) {
|
if (optional.isPresent()) {
|
||||||
|
|||||||
@@ -11,4 +11,9 @@ public class FurnitureCollisionPacketHandler implements EntityPacketHandler {
|
|||||||
public void handleSyncEntityPosition(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
public void handleSyncEntityPosition(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMove(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -24,4 +24,9 @@ public class FurniturePacketHandler implements EntityPacketHandler {
|
|||||||
public void handleSyncEntityPosition(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
public void handleSyncEntityPosition(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMove(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class ProjectilePacketHandler implements EntityPacketHandler {
|
|||||||
buf.writeVarInt(event.packetID());
|
buf.writeVarInt(event.packetID());
|
||||||
buf.writeVarInt(this.entityId);
|
buf.writeVarInt(this.entityId);
|
||||||
buf.writeUUID(uuid);
|
buf.writeUUID(uuid);
|
||||||
buf.writeVarInt(MEntityTypes.instance$EntityType$ITEM_DISPLAY$registryId);
|
buf.writeVarInt(MEntityTypes.ITEM_DISPLAY$registryId);
|
||||||
buf.writeDouble(x);
|
buf.writeDouble(x);
|
||||||
buf.writeDouble(y);
|
buf.writeDouble(y);
|
||||||
buf.writeDouble(z);
|
buf.writeDouble(z);
|
||||||
|
|||||||
@@ -139,4 +139,14 @@ public class PacketIds1_20 implements PacketIds {
|
|||||||
public int serverboundSetCreativeModeSlotPacket() {
|
public int serverboundSetCreativeModeSlotPacket() {
|
||||||
return PacketIdFinder.serverboundByClazz(NetworkReflections.clazz$ServerboundSetCreativeModeSlotPacket);
|
return PacketIdFinder.serverboundByClazz(NetworkReflections.clazz$ServerboundSetCreativeModeSlotPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int clientboundBlockEventPacket() {
|
||||||
|
return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundBlockEventPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int serverboundInteractPacket() {
|
||||||
|
return PacketIdFinder.serverboundByClazz(NetworkReflections.clazz$ServerboundInteractPacket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,11 @@ public class PacketIds1_20_5 implements PacketIds {
|
|||||||
return PacketIdFinder.clientboundByName("minecraft:set_player_inventory");
|
return PacketIdFinder.clientboundByName("minecraft:set_player_inventory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int clientboundBlockEventPacket() {
|
||||||
|
return PacketIdFinder.clientboundByName("minecraft:block_event");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int serverboundContainerClickPacket() {
|
public int serverboundContainerClickPacket() {
|
||||||
return PacketIdFinder.serverboundByName("minecraft:container_click");
|
return PacketIdFinder.serverboundByName("minecraft:container_click");
|
||||||
@@ -138,4 +143,9 @@ public class PacketIds1_20_5 implements PacketIds {
|
|||||||
public int serverboundSetCreativeModeSlotPacket() {
|
public int serverboundSetCreativeModeSlotPacket() {
|
||||||
return PacketIdFinder.serverboundByName("minecraft:set_creative_mode_slot");
|
return PacketIdFinder.serverboundByName("minecraft:set_creative_mode_slot");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int serverboundInteractPacket() {
|
||||||
|
return PacketIdFinder.serverboundByName("minecraft:interact");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,15 @@ import com.google.gson.JsonElement;
|
|||||||
import com.mojang.serialization.DynamicOps;
|
import com.mojang.serialization.DynamicOps;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||||
import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils;
|
import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils;
|
||||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -1353,10 +1356,6 @@ public final class CoreReflections {
|
|||||||
ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, clazz$VoxelShape, new String[]{"getBlockSupportShape", "b_"}, clazz$BlockState, clazz$BlockGetter, CoreReflections.clazz$BlockPos)
|
ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, clazz$VoxelShape, new String[]{"getBlockSupportShape", "b_"}, clazz$BlockState, clazz$BlockGetter, CoreReflections.clazz$BlockPos)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final Method method$LevelAccessor$scheduleTick = requireNonNull(
|
|
||||||
ReflectionUtils.getMethod(clazz$LevelAccessor, void.class, CoreReflections.clazz$BlockPos, clazz$Block, int.class)
|
|
||||||
);
|
|
||||||
|
|
||||||
public static final Field field$BlockBehaviour$properties = requireNonNull(
|
public static final Field field$BlockBehaviour$properties = requireNonNull(
|
||||||
ReflectionUtils.getInstanceDeclaredField(clazz$BlockBehaviour, clazz$BlockBehaviour$Properties, 0)
|
ReflectionUtils.getInstanceDeclaredField(clazz$BlockBehaviour, clazz$BlockBehaviour$Properties, 0)
|
||||||
);
|
);
|
||||||
@@ -3265,4 +3264,48 @@ public final class CoreReflections {
|
|||||||
public static final Method method$Registry$asLookup = ReflectionUtils.getMethod(
|
public static final Method method$Registry$asLookup = ReflectionUtils.getMethod(
|
||||||
clazz$Registry, clazz$HolderLookup$RegistryLookup, new String[]{"asLookup", "p"}
|
clazz$Registry, clazz$HolderLookup$RegistryLookup, new String[]{"asLookup", "p"}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static final Field field$ServerEntity$broadcast = requireNonNull(
|
||||||
|
ReflectionUtils.getDeclaredField(
|
||||||
|
clazz$ServerEntity, Consumer.class, 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
public static final MethodHandle methodHandle$ServerEntity$broadcastSetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerEntity$updateIntervalSetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerPlayer$connectionGetter;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
methodHandle$ServerEntity$broadcastSetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectSetter(field$ServerEntity$broadcast)
|
||||||
|
.asType(MethodType.methodType(void.class, Object.class, Consumer.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerEntity$updateIntervalSetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectSetter(field$ServerEntity$updateInterval)
|
||||||
|
.asType(MethodType.methodType(void.class, Object.class, int.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerPlayer$connectionGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerPlayer$connection)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new ReflectionInitException("Failed to initialize reflection", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Class<?> clazz$BaseFireBlock = requireNonNull(
|
||||||
|
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||||
|
"world.level.block.BlockFireAbstract",
|
||||||
|
"world.level.block.BaseFireBlock"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
public static final Method method$BaseFireBlock$canBePlacedAt = requireNonNull(
|
||||||
|
ReflectionUtils.getStaticMethod(clazz$BaseFireBlock, boolean.class, clazz$Level, clazz$BlockPos, clazz$Direction)
|
||||||
|
);
|
||||||
|
|
||||||
|
public static final Field field$FireBlock$igniteOdds = requireNonNull(
|
||||||
|
ReflectionUtils.getDeclaredField(clazz$FireBlock, Object2IntMap.class, 0)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ public final class MBlocks {
|
|||||||
public static final Object ICE;
|
public static final Object ICE;
|
||||||
public static final Object SHORT_GRASS;
|
public static final Object SHORT_GRASS;
|
||||||
public static final Object SHORT_GRASS$defaultState;
|
public static final Object SHORT_GRASS$defaultState;
|
||||||
|
public static final Object SHULKER_BOX;
|
||||||
|
public static final Object COMPOSTER;
|
||||||
|
|
||||||
private static Object getById(String id) throws ReflectiveOperationException {
|
private static Object getById(String id) throws ReflectiveOperationException {
|
||||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||||
@@ -33,6 +35,8 @@ public final class MBlocks {
|
|||||||
ICE = getById("ice");
|
ICE = getById("ice");
|
||||||
SHORT_GRASS = getById(VersionHelper.isOrAbove1_20_3() ? "short_grass" : "grass");
|
SHORT_GRASS = getById(VersionHelper.isOrAbove1_20_3() ? "short_grass" : "grass");
|
||||||
SHORT_GRASS$defaultState = CoreReflections.method$Block$defaultBlockState.invoke(SHORT_GRASS);
|
SHORT_GRASS$defaultState = CoreReflections.method$Block$defaultBlockState.invoke(SHORT_GRASS);
|
||||||
|
SHULKER_BOX = getById("shulker_box");
|
||||||
|
COMPOSTER = getById("composter");
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new ReflectionInitException("Failed to init Blocks", e);
|
throw new ReflectionInitException("Failed to init Blocks", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,50 +7,50 @@ import net.momirealms.craftengine.core.util.VersionHelper;
|
|||||||
public final class MEntityTypes {
|
public final class MEntityTypes {
|
||||||
private MEntityTypes() {}
|
private MEntityTypes() {}
|
||||||
|
|
||||||
public static final Object instance$EntityType$TEXT_DISPLAY;
|
public static final Object TEXT_DISPLAY;
|
||||||
public static final int instance$EntityType$TEXT_DISPLAY$registryId;
|
public static final int TEXT_DISPLAY$registryId;
|
||||||
public static final Object instance$EntityType$ITEM_DISPLAY;
|
public static final Object ITEM_DISPLAY;
|
||||||
public static final int instance$EntityType$ITEM_DISPLAY$registryId;
|
public static final int ITEM_DISPLAY$registryId;
|
||||||
public static final Object instance$EntityType$BLOCK_DISPLAY;
|
public static final Object BLOCK_DISPLAY;
|
||||||
public static final int instance$EntityType$BLOCK_DISPLAY$registryId;
|
public static final int BLOCK_DISPLAY$registryId;
|
||||||
public static final Object instance$EntityType$ARMOR_STAND;
|
public static final Object ARMOR_STAND;
|
||||||
public static final int instance$EntityType$ARMOR_STAND$registryId;
|
public static final int ARMOR_STAND$registryId;
|
||||||
public static final Object instance$EntityType$FALLING_BLOCK;
|
public static final Object FALLING_BLOCK;
|
||||||
public static final int instance$EntityType$FALLING_BLOCK$registryId;
|
public static final int FALLING_BLOCK$registryId;
|
||||||
public static final Object instance$EntityType$INTERACTION;
|
public static final Object INTERACTION;
|
||||||
public static final int instance$EntityType$INTERACTION$registryId;
|
public static final int INTERACTION$registryId;
|
||||||
public static final Object instance$EntityType$SHULKER;
|
public static final Object SHULKER;
|
||||||
public static final int instance$EntityType$SHULKER$registryId;
|
public static final int SHULKER$registryId;
|
||||||
public static final Object instance$EntityType$OAK_BOAT;
|
public static final Object OAK_BOAT;
|
||||||
public static final int instance$EntityType$OAK_BOAT$registryId;
|
public static final int OAK_BOAT$registryId;
|
||||||
public static final Object instance$EntityType$TRIDENT;
|
public static final Object TRIDENT;
|
||||||
public static final int instance$EntityType$TRIDENT$registryId;
|
public static final int TRIDENT$registryId;
|
||||||
public static final Object instance$EntityType$SNOWBALL;
|
public static final Object SNOWBALL;
|
||||||
public static final int instance$EntityType$SNOWBALL$registryId;
|
public static final int SNOWBALL$registryId;
|
||||||
public static final Object instance$EntityType$FIREBALL;
|
public static final Object FIREBALL;
|
||||||
public static final int instance$EntityType$FIREBALL$registryId;
|
public static final int FIREBALL$registryId;
|
||||||
public static final Object instance$EntityType$EYE_OF_ENDER;
|
public static final Object EYE_OF_ENDER;
|
||||||
public static final int instance$EntityType$EYE_OF_ENDER$registryId;
|
public static final int EYE_OF_ENDER$registryId;
|
||||||
public static final Object instance$EntityType$FIREWORK_ROCKET;
|
public static final Object FIREWORK_ROCKET;
|
||||||
public static final int instance$EntityType$FIREWORK_ROCKET$registryId;
|
public static final int FIREWORK_ROCKET$registryId;
|
||||||
public static final Object instance$EntityType$ITEM;
|
public static final Object ITEM;
|
||||||
public static final int instance$EntityType$ITEM$registryId;
|
public static final int ITEM$registryId;
|
||||||
public static final Object instance$EntityType$ITEM_FRAME;
|
public static final Object ITEM_FRAME;
|
||||||
public static final int instance$EntityType$ITEM_FRAME$registryId;
|
public static final int ITEM_FRAME$registryId;
|
||||||
public static final Object instance$EntityType$GLOW_ITEM_FRAME;
|
public static final Object GLOW_ITEM_FRAME;
|
||||||
public static final int instance$EntityType$GLOW_ITEM_FRAME$registryId;
|
public static final int GLOW_ITEM_FRAME$registryId;
|
||||||
public static final Object instance$EntityType$OMINOUS_ITEM_SPAWNER;
|
public static final Object OMINOUS_ITEM_SPAWNER;
|
||||||
public static final int instance$EntityType$OMINOUS_ITEM_SPAWNER$registryId;
|
public static final int OMINOUS_ITEM_SPAWNER$registryId;
|
||||||
public static final Object instance$EntityType$SMALL_FIREBALL;
|
public static final Object SMALL_FIREBALL;
|
||||||
public static final int instance$EntityType$SMALL_FIREBALL$registryId;
|
public static final int SMALL_FIREBALL$registryId;
|
||||||
public static final Object instance$EntityType$EGG;
|
public static final Object EGG;
|
||||||
public static final int instance$EntityType$EGG$registryId;
|
public static final int EGG$registryId;
|
||||||
public static final Object instance$EntityType$ENDER_PEARL;
|
public static final Object ENDER_PEARL;
|
||||||
public static final int instance$EntityType$ENDER_PEARL$registryId;
|
public static final int ENDER_PEARL$registryId;
|
||||||
public static final Object instance$EntityType$EXPERIENCE_BOTTLE;
|
public static final Object EXPERIENCE_BOTTLE;
|
||||||
public static final int instance$EntityType$EXPERIENCE_BOTTLE$registryId;
|
public static final int EXPERIENCE_BOTTLE$registryId;
|
||||||
public static final Object instance$EntityType$POTION;
|
public static final Object POTION;
|
||||||
public static final int instance$EntityType$POTION$registryId;
|
public static final int POTION$registryId;
|
||||||
|
|
||||||
private static Object getById(String id) throws ReflectiveOperationException {
|
private static Object getById(String id) throws ReflectiveOperationException {
|
||||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||||
@@ -64,50 +64,50 @@ public final class MEntityTypes {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
instance$EntityType$TEXT_DISPLAY = getById("text_display");
|
TEXT_DISPLAY = getById("text_display");
|
||||||
instance$EntityType$TEXT_DISPLAY$registryId = getRegistryId(instance$EntityType$TEXT_DISPLAY);
|
TEXT_DISPLAY$registryId = getRegistryId(TEXT_DISPLAY);
|
||||||
instance$EntityType$ITEM_DISPLAY = getById("item_display");
|
ITEM_DISPLAY = getById("item_display");
|
||||||
instance$EntityType$ITEM_DISPLAY$registryId = getRegistryId(instance$EntityType$ITEM_DISPLAY);
|
ITEM_DISPLAY$registryId = getRegistryId(ITEM_DISPLAY);
|
||||||
instance$EntityType$BLOCK_DISPLAY = getById("block_display");
|
BLOCK_DISPLAY = getById("block_display");
|
||||||
instance$EntityType$BLOCK_DISPLAY$registryId = getRegistryId(instance$EntityType$BLOCK_DISPLAY);
|
BLOCK_DISPLAY$registryId = getRegistryId(BLOCK_DISPLAY);
|
||||||
instance$EntityType$FALLING_BLOCK = getById("falling_block");
|
FALLING_BLOCK = getById("falling_block");
|
||||||
instance$EntityType$FALLING_BLOCK$registryId = getRegistryId(instance$EntityType$FALLING_BLOCK);
|
FALLING_BLOCK$registryId = getRegistryId(FALLING_BLOCK);
|
||||||
instance$EntityType$INTERACTION = getById("interaction");
|
INTERACTION = getById("interaction");
|
||||||
instance$EntityType$INTERACTION$registryId = getRegistryId(instance$EntityType$INTERACTION);
|
INTERACTION$registryId = getRegistryId(INTERACTION);
|
||||||
instance$EntityType$SHULKER = getById("shulker");
|
SHULKER = getById("shulker");
|
||||||
instance$EntityType$SHULKER$registryId = getRegistryId(instance$EntityType$SHULKER);
|
SHULKER$registryId = getRegistryId(SHULKER);
|
||||||
instance$EntityType$ARMOR_STAND = getById("armor_stand");
|
ARMOR_STAND = getById("armor_stand");
|
||||||
instance$EntityType$ARMOR_STAND$registryId = getRegistryId(instance$EntityType$ARMOR_STAND);
|
ARMOR_STAND$registryId = getRegistryId(ARMOR_STAND);
|
||||||
instance$EntityType$OAK_BOAT = getById(VersionHelper.isOrAbove1_21_2() ? "oak_boat" : "boat");
|
OAK_BOAT = getById(VersionHelper.isOrAbove1_21_2() ? "oak_boat" : "boat");
|
||||||
instance$EntityType$OAK_BOAT$registryId = getRegistryId(instance$EntityType$OAK_BOAT);
|
OAK_BOAT$registryId = getRegistryId(OAK_BOAT);
|
||||||
instance$EntityType$TRIDENT = getById("trident");
|
TRIDENT = getById("trident");
|
||||||
instance$EntityType$TRIDENT$registryId = getRegistryId(instance$EntityType$TRIDENT);
|
TRIDENT$registryId = getRegistryId(TRIDENT);
|
||||||
instance$EntityType$SNOWBALL = getById("snowball");
|
SNOWBALL = getById("snowball");
|
||||||
instance$EntityType$SNOWBALL$registryId = getRegistryId(instance$EntityType$SNOWBALL);
|
SNOWBALL$registryId = getRegistryId(SNOWBALL);
|
||||||
instance$EntityType$FIREBALL = getById("fireball");
|
FIREBALL = getById("fireball");
|
||||||
instance$EntityType$FIREBALL$registryId = getRegistryId(instance$EntityType$FIREBALL);
|
FIREBALL$registryId = getRegistryId(FIREBALL);
|
||||||
instance$EntityType$EYE_OF_ENDER = getById("eye_of_ender");
|
EYE_OF_ENDER = getById("eye_of_ender");
|
||||||
instance$EntityType$EYE_OF_ENDER$registryId = getRegistryId(instance$EntityType$EYE_OF_ENDER);
|
EYE_OF_ENDER$registryId = getRegistryId(EYE_OF_ENDER);
|
||||||
instance$EntityType$FIREWORK_ROCKET = getById("firework_rocket");
|
FIREWORK_ROCKET = getById("firework_rocket");
|
||||||
instance$EntityType$FIREWORK_ROCKET$registryId = getRegistryId(instance$EntityType$FIREWORK_ROCKET);
|
FIREWORK_ROCKET$registryId = getRegistryId(FIREWORK_ROCKET);
|
||||||
instance$EntityType$ITEM = getById("item");
|
ITEM = getById("item");
|
||||||
instance$EntityType$ITEM$registryId = getRegistryId(instance$EntityType$ITEM);
|
ITEM$registryId = getRegistryId(ITEM);
|
||||||
instance$EntityType$ITEM_FRAME = getById("item_frame");
|
ITEM_FRAME = getById("item_frame");
|
||||||
instance$EntityType$ITEM_FRAME$registryId = getRegistryId(instance$EntityType$ITEM_FRAME);
|
ITEM_FRAME$registryId = getRegistryId(ITEM_FRAME);
|
||||||
instance$EntityType$GLOW_ITEM_FRAME = getById("glow_item_frame");
|
GLOW_ITEM_FRAME = getById("glow_item_frame");
|
||||||
instance$EntityType$GLOW_ITEM_FRAME$registryId = getRegistryId(instance$EntityType$GLOW_ITEM_FRAME);
|
GLOW_ITEM_FRAME$registryId = getRegistryId(GLOW_ITEM_FRAME);
|
||||||
instance$EntityType$SMALL_FIREBALL = getById("small_fireball");
|
SMALL_FIREBALL = getById("small_fireball");
|
||||||
instance$EntityType$SMALL_FIREBALL$registryId = getRegistryId(instance$EntityType$SMALL_FIREBALL);
|
SMALL_FIREBALL$registryId = getRegistryId(SMALL_FIREBALL);
|
||||||
instance$EntityType$EGG = getById("egg");
|
EGG = getById("egg");
|
||||||
instance$EntityType$EGG$registryId = getRegistryId(instance$EntityType$EGG);
|
EGG$registryId = getRegistryId(EGG);
|
||||||
instance$EntityType$ENDER_PEARL = getById("ender_pearl");
|
ENDER_PEARL = getById("ender_pearl");
|
||||||
instance$EntityType$ENDER_PEARL$registryId = getRegistryId(instance$EntityType$ENDER_PEARL);
|
ENDER_PEARL$registryId = getRegistryId(ENDER_PEARL);
|
||||||
instance$EntityType$EXPERIENCE_BOTTLE = getById("experience_bottle");
|
EXPERIENCE_BOTTLE = getById("experience_bottle");
|
||||||
instance$EntityType$EXPERIENCE_BOTTLE$registryId = getRegistryId(instance$EntityType$EXPERIENCE_BOTTLE);
|
EXPERIENCE_BOTTLE$registryId = getRegistryId(EXPERIENCE_BOTTLE);
|
||||||
instance$EntityType$POTION = getById("potion");
|
POTION = getById("potion");
|
||||||
instance$EntityType$POTION$registryId = getRegistryId(instance$EntityType$POTION);
|
POTION$registryId = getRegistryId(POTION);
|
||||||
instance$EntityType$OMINOUS_ITEM_SPAWNER = VersionHelper.isOrAbove1_20_5() ? getById("ominous_item_spawner") : null;
|
OMINOUS_ITEM_SPAWNER = VersionHelper.isOrAbove1_20_5() ? getById("ominous_item_spawner") : null;
|
||||||
instance$EntityType$OMINOUS_ITEM_SPAWNER$registryId = getRegistryId(instance$EntityType$OMINOUS_ITEM_SPAWNER);
|
OMINOUS_ITEM_SPAWNER$registryId = getRegistryId(OMINOUS_ITEM_SPAWNER);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new ReflectionInitException("Failed to init EntityTypes", e);
|
throw new ReflectionInitException("Failed to init EntityTypes", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,21 +10,23 @@ import java.lang.reflect.Type;
|
|||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
public final class MRegistries {
|
public final class MRegistries {
|
||||||
public static final Object instance$Registries$BLOCK;
|
public static final Object BLOCK;
|
||||||
public static final Object instance$Registries$ITEM;
|
public static final Object ITEM;
|
||||||
public static final Object instance$Registries$ATTRIBUTE;
|
public static final Object ATTRIBUTE;
|
||||||
public static final Object instance$Registries$BIOME;
|
public static final Object BIOME;
|
||||||
public static final Object instance$Registries$MOB_EFFECT;
|
public static final Object MOB_EFFECT;
|
||||||
public static final Object instance$Registries$SOUND_EVENT;
|
public static final Object SOUND_EVENT;
|
||||||
public static final Object instance$Registries$PARTICLE_TYPE;
|
public static final Object PARTICLE_TYPE;
|
||||||
public static final Object instance$Registries$ENTITY_TYPE;
|
public static final Object ENTITY_TYPE;
|
||||||
public static final Object instance$Registries$FLUID;
|
public static final Object FLUID;
|
||||||
public static final Object instance$Registries$RECIPE_TYPE;
|
public static final Object RECIPE_TYPE;
|
||||||
public static final Object instance$Registries$DIMENSION_TYPE;
|
public static final Object DIMENSION_TYPE;
|
||||||
public static final Object instance$Registries$CONFIGURED_FEATURE;
|
public static final Object CONFIGURED_FEATURE;
|
||||||
public static final Object instance$Registries$PLACED_FEATURE;
|
public static final Object PLACED_FEATURE;
|
||||||
@Nullable // 1.21+
|
@Nullable // 1.21+
|
||||||
public static final Object instance$Registries$JUKEBOX_SONG;
|
public static final Object JUKEBOX_SONG;
|
||||||
|
@Nullable // 1.21+
|
||||||
|
public static final Object RECIPE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Field[] fields = CoreReflections.clazz$Registries.getDeclaredFields();
|
Field[] fields = CoreReflections.clazz$Registries.getDeclaredFields();
|
||||||
@@ -43,6 +45,7 @@ public final class MRegistries {
|
|||||||
Object registries$ConfiguredFeature = null;
|
Object registries$ConfiguredFeature = null;
|
||||||
Object registries$PlacedFeature = null;
|
Object registries$PlacedFeature = null;
|
||||||
Object registries$JukeboxSong = null;
|
Object registries$JukeboxSong = null;
|
||||||
|
Object registries$Recipe = null;
|
||||||
for (Field field : fields) {
|
for (Field field : fields) {
|
||||||
Type fieldType = field.getGenericType();
|
Type fieldType = field.getGenericType();
|
||||||
if (fieldType instanceof ParameterizedType paramType) {
|
if (fieldType instanceof ParameterizedType paramType) {
|
||||||
@@ -60,6 +63,8 @@ public final class MRegistries {
|
|||||||
registries$RecipeType = field.get(null);
|
registries$RecipeType = field.get(null);
|
||||||
} else if (rawType == CoreReflections.clazz$ConfiguredFeature) {
|
} else if (rawType == CoreReflections.clazz$ConfiguredFeature) {
|
||||||
registries$ConfiguredFeature = field.get(null);
|
registries$ConfiguredFeature = field.get(null);
|
||||||
|
} else if (rawType == CoreReflections.clazz$Recipe) {
|
||||||
|
registries$Recipe = field.get(null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (type == CoreReflections.clazz$Block) {
|
if (type == CoreReflections.clazz$Block) {
|
||||||
@@ -88,20 +93,21 @@ public final class MRegistries {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
instance$Registries$BLOCK = requireNonNull(registries$Block);
|
BLOCK = requireNonNull(registries$Block);
|
||||||
instance$Registries$ITEM = requireNonNull(registries$Item);
|
ITEM = requireNonNull(registries$Item);
|
||||||
instance$Registries$ATTRIBUTE = requireNonNull(registries$Attribute);
|
ATTRIBUTE = requireNonNull(registries$Attribute);
|
||||||
instance$Registries$BIOME = requireNonNull(registries$Biome);
|
BIOME = requireNonNull(registries$Biome);
|
||||||
instance$Registries$MOB_EFFECT = requireNonNull(registries$MobEffect);
|
MOB_EFFECT = requireNonNull(registries$MobEffect);
|
||||||
instance$Registries$SOUND_EVENT = requireNonNull(registries$SoundEvent);
|
SOUND_EVENT = requireNonNull(registries$SoundEvent);
|
||||||
instance$Registries$DIMENSION_TYPE = requireNonNull(registries$DimensionType);
|
DIMENSION_TYPE = requireNonNull(registries$DimensionType);
|
||||||
instance$Registries$PARTICLE_TYPE = requireNonNull(registries$ParticleType);
|
PARTICLE_TYPE = requireNonNull(registries$ParticleType);
|
||||||
instance$Registries$ENTITY_TYPE = requireNonNull(registries$EntityType);
|
ENTITY_TYPE = requireNonNull(registries$EntityType);
|
||||||
instance$Registries$FLUID = requireNonNull(registries$Fluid);
|
FLUID = requireNonNull(registries$Fluid);
|
||||||
instance$Registries$RECIPE_TYPE = requireNonNull(registries$RecipeType);
|
RECIPE_TYPE = requireNonNull(registries$RecipeType);
|
||||||
instance$Registries$CONFIGURED_FEATURE = requireNonNull(registries$ConfiguredFeature);
|
CONFIGURED_FEATURE = requireNonNull(registries$ConfiguredFeature);
|
||||||
instance$Registries$PLACED_FEATURE = requireNonNull(registries$PlacedFeature);
|
PLACED_FEATURE = requireNonNull(registries$PlacedFeature);
|
||||||
instance$Registries$JUKEBOX_SONG = registries$JukeboxSong;
|
JUKEBOX_SONG = registries$JukeboxSong;
|
||||||
|
RECIPE = registries$Recipe;
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils;
|
|||||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
import net.momirealms.sparrow.nbt.Tag;
|
import net.momirealms.sparrow.nbt.Tag;
|
||||||
|
import net.momirealms.sparrow.nbt.codec.LegacyJavaOps;
|
||||||
import net.momirealms.sparrow.nbt.codec.LegacyNBTOps;
|
import net.momirealms.sparrow.nbt.codec.LegacyNBTOps;
|
||||||
import net.momirealms.sparrow.nbt.codec.NBTOps;
|
import net.momirealms.sparrow.nbt.codec.NBTOps;
|
||||||
|
|
||||||
@@ -34,8 +35,12 @@ public class MRegistryOps {
|
|||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
if (clazz$JavaOps != null) {
|
if (clazz$JavaOps != null) {
|
||||||
|
// 1.20.5+
|
||||||
Object javaOps = ReflectionUtils.getDeclaredField(clazz$JavaOps, clazz$JavaOps, 0).get(null);
|
Object javaOps = ReflectionUtils.getDeclaredField(clazz$JavaOps, clazz$JavaOps, 0).get(null);
|
||||||
JAVA = (DynamicOps<Object>) CoreReflections.method$RegistryOps$create.invoke(null, javaOps, FastNMS.INSTANCE.registryAccess());
|
JAVA = (DynamicOps<Object>) CoreReflections.method$RegistryOps$create.invoke(null, javaOps, FastNMS.INSTANCE.registryAccess());
|
||||||
|
} else if (!VersionHelper.isOrAbove1_20_5()) {
|
||||||
|
// 1.20.1-1.20.4
|
||||||
|
JAVA = (DynamicOps<Object>) CoreReflections.method$RegistryOps$create.invoke(null, LegacyJavaOps.INSTANCE, FastNMS.INSTANCE.registryAccess());
|
||||||
} else {
|
} else {
|
||||||
JAVA = null;
|
JAVA = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||||
import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils;
|
import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils;
|
||||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
@@ -968,7 +971,7 @@ public final class NetworkReflections {
|
|||||||
);
|
);
|
||||||
|
|
||||||
public static final Field field$ServerboundEditBookPacket$slot = requireNonNull(
|
public static final Field field$ServerboundEditBookPacket$slot = requireNonNull(
|
||||||
ReflectionUtils.getDeclaredField(clazz$ServerboundEditBookPacket, int.class, 0)
|
ReflectionUtils.getDeclaredField(clazz$ServerboundEditBookPacket, int.class, VersionHelper.isOrAbove1_20_5() ? 0 : 4)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final Field field$ServerboundEditBookPacket$pages = requireNonNull(
|
public static final Field field$ServerboundEditBookPacket$pages = requireNonNull(
|
||||||
@@ -1293,4 +1296,177 @@ public final class NetworkReflections {
|
|||||||
public static final Constructor<?> constructor$ClientboundTickingStatePacket = Optional.ofNullable(clazz$ClientboundTickingStatePacket)
|
public static final Constructor<?> constructor$ClientboundTickingStatePacket = Optional.ofNullable(clazz$ClientboundTickingStatePacket)
|
||||||
.map(it -> ReflectionUtils.getConstructor(it, float.class, boolean.class))
|
.map(it -> ReflectionUtils.getConstructor(it, float.class, boolean.class))
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
||||||
|
public static final Class<?> clazz$ClientboundBlockEventPacket = requireNonNull(
|
||||||
|
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||||
|
"network.protocol.game.PacketPlayOutBlockAction",
|
||||||
|
"network.protocol.game.ClientboundBlockEventPacket"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
public static final MethodHandle methodHandle$ServerboundRenameItemPacket$nameGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundRenameItemPacket$nameSetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundHelloPacket$nameGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundHelloPacket$uuidGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundSetCreativeModeSlotPacket$itemStackGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundSetCreativeModeSlotPacket$slotNumGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundInteractPacket$actionGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundInteractPacket$InteractionAtLocationAction$handGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundInteractPacket$InteractionAtLocationAction$locationGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundSignUpdatePacket$linesGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundEditBookPacket$pagesGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundEditBookPacket$titleGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundEditBookPacket$slotGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundResourcePackPacket$actionGetter;
|
||||||
|
public static final MethodHandle methodHandle$ClientboundEntityEventPacket$entityIdGetter;
|
||||||
|
public static final MethodHandle methodHandle$ClientboundEntityEventPacket$eventIdGetter;
|
||||||
|
public static final MethodHandle methodHandle$ClientIntentionPacket$protocolVersionGetter;
|
||||||
|
public static final MethodHandle methodHandle$ClientboundRespawnPacket$dimensionGetter;
|
||||||
|
public static final MethodHandle methodHandle$ClientboundRespawnPacket$commonPlayerSpawnInfoGetter;
|
||||||
|
public static final MethodHandle methodHandle$CommonPlayerSpawnInfo$dimensionGetter;
|
||||||
|
public static final MethodHandle methodHandle$ClientboundLoginPacket$dimensionGetter;
|
||||||
|
public static final MethodHandle methodHandle$ClientboundLoginPacket$commonPlayerSpawnInfoGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundPickItemFromBlockPacket$posGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundPickItemFromEntityPacket$idGetter;
|
||||||
|
public static final MethodHandle methodHandle$ServerboundCustomPayloadPacket$payloadGetter;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
methodHandle$ServerboundRenameItemPacket$nameGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundRenameItemPacket$name)
|
||||||
|
.asType(MethodType.methodType(String.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundRenameItemPacket$nameSetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectSetter(field$ServerboundRenameItemPacket$name)
|
||||||
|
.asType(MethodType.methodType(void.class, Object.class, String.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundHelloPacket$nameGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundHelloPacket$name)
|
||||||
|
.asType(MethodType.methodType(String.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundHelloPacket$uuidGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundHelloPacket$uuid)
|
||||||
|
.asType(MethodType.methodType(VersionHelper.isOrAbove1_20_2() ? UUID.class : Optional.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundSetCreativeModeSlotPacket$itemStackGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundSetCreativeModeSlotPacket$itemStack)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundSetCreativeModeSlotPacket$slotNumGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundSetCreativeModeSlotPacket$slotNum)
|
||||||
|
.asType(MethodType.methodType(VersionHelper.isOrAbove1_20_5() ? short.class : int.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundInteractPacket$actionGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundInteractPacket$action)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundInteractPacket$InteractionAtLocationAction$handGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundInteractPacket$InteractionAtLocationAction$hand)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundInteractPacket$InteractionAtLocationAction$locationGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundInteractPacket$InteractionAtLocationAction$location)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundSignUpdatePacket$linesGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundSignUpdatePacket$lines)
|
||||||
|
.asType(MethodType.methodType(String[].class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundEditBookPacket$pagesGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundEditBookPacket$pages)
|
||||||
|
.asType(MethodType.methodType(List.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundEditBookPacket$titleGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundEditBookPacket$title)
|
||||||
|
.asType(MethodType.methodType(Optional.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundEditBookPacket$slotGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundEditBookPacket$slot)
|
||||||
|
.asType(MethodType.methodType(int.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ServerboundResourcePackPacket$actionGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundResourcePackPacket$action)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ClientboundEntityEventPacket$entityIdGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ClientboundEntityEventPacket$entityId)
|
||||||
|
.asType(MethodType.methodType(int.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ClientboundEntityEventPacket$eventIdGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ClientboundEntityEventPacket$eventId)
|
||||||
|
.asType(MethodType.methodType(byte.class, Object.class))
|
||||||
|
);
|
||||||
|
methodHandle$ClientIntentionPacket$protocolVersionGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ClientIntentionPacket$protocolVersion)
|
||||||
|
.asType(MethodType.methodType(int.class, Object.class))
|
||||||
|
);
|
||||||
|
if (field$ServerboundCustomPayloadPacket$payload != null) {
|
||||||
|
methodHandle$ServerboundCustomPayloadPacket$payloadGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundCustomPayloadPacket$payload)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
methodHandle$ServerboundCustomPayloadPacket$payloadGetter = null;
|
||||||
|
}
|
||||||
|
if (field$ServerboundPickItemFromEntityPacket$id != null) {
|
||||||
|
methodHandle$ServerboundPickItemFromEntityPacket$idGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundPickItemFromEntityPacket$id)
|
||||||
|
.asType(MethodType.methodType(int.class, Object.class))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
methodHandle$ServerboundPickItemFromEntityPacket$idGetter = null;
|
||||||
|
}
|
||||||
|
if (field$ServerboundPickItemFromBlockPacket$pos != null) {
|
||||||
|
methodHandle$ServerboundPickItemFromBlockPacket$posGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ServerboundPickItemFromBlockPacket$pos)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
methodHandle$ServerboundPickItemFromBlockPacket$posGetter = null;
|
||||||
|
}
|
||||||
|
if (field$ClientboundLoginPacket$commonPlayerSpawnInfo != null) {
|
||||||
|
methodHandle$ClientboundLoginPacket$commonPlayerSpawnInfoGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ClientboundLoginPacket$commonPlayerSpawnInfo)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
methodHandle$ClientboundLoginPacket$commonPlayerSpawnInfoGetter = null;
|
||||||
|
}
|
||||||
|
if (field$ClientboundLoginPacket$dimension != null) {
|
||||||
|
methodHandle$ClientboundLoginPacket$dimensionGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ClientboundLoginPacket$dimension)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
methodHandle$ClientboundLoginPacket$dimensionGetter = null;
|
||||||
|
}
|
||||||
|
if (field$CommonPlayerSpawnInfo$dimension != null) {
|
||||||
|
methodHandle$CommonPlayerSpawnInfo$dimensionGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$CommonPlayerSpawnInfo$dimension)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
methodHandle$CommonPlayerSpawnInfo$dimensionGetter = null;
|
||||||
|
}
|
||||||
|
if (field$ClientboundRespawnPacket$commonPlayerSpawnInfo != null) {
|
||||||
|
methodHandle$ClientboundRespawnPacket$commonPlayerSpawnInfoGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ClientboundRespawnPacket$commonPlayerSpawnInfo)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
methodHandle$ClientboundRespawnPacket$commonPlayerSpawnInfoGetter = null;
|
||||||
|
}
|
||||||
|
if (field$ClientboundRespawnPacket$dimension != null) {
|
||||||
|
methodHandle$ClientboundRespawnPacket$dimensionGetter = requireNonNull(
|
||||||
|
ReflectionUtils.unreflectGetter(field$ClientboundRespawnPacket$dimension)
|
||||||
|
.asType(MethodType.methodType(Object.class, Object.class))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
methodHandle$ClientboundRespawnPacket$dimensionGetter = null;
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new ReflectionInitException("Failed to initialize reflection", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,12 @@ import net.momirealms.craftengine.core.plugin.context.CooldownData;
|
|||||||
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||||
import net.momirealms.craftengine.core.plugin.network.ProtocolVersion;
|
import net.momirealms.craftengine.core.plugin.network.ProtocolVersion;
|
||||||
|
import net.momirealms.craftengine.core.sound.SoundSource;
|
||||||
import net.momirealms.craftengine.core.util.Direction;
|
import net.momirealms.craftengine.core.util.Direction;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
import net.momirealms.craftengine.core.world.BlockPos;
|
import net.momirealms.craftengine.core.world.BlockPos;
|
||||||
|
import net.momirealms.craftengine.core.world.Position;
|
||||||
import net.momirealms.craftengine.core.world.World;
|
import net.momirealms.craftengine.core.world.World;
|
||||||
import net.momirealms.craftengine.core.world.WorldEvents;
|
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
@@ -138,17 +140,17 @@ public class BukkitServerPlayer extends Player {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Channel nettyChannel() {
|
public Channel nettyChannel() {
|
||||||
return channel;
|
return this.channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CraftEngine plugin() {
|
public CraftEngine plugin() {
|
||||||
return plugin;
|
return this.plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMiningBlock() {
|
public boolean isMiningBlock() {
|
||||||
return destroyPos != null;
|
return this.destroyPos != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDestroyedState(Object destroyedState) {
|
public void setDestroyedState(Object destroyedState) {
|
||||||
@@ -221,8 +223,8 @@ public class BukkitServerPlayer extends Player {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateLastSuccessfulInteractionTick(int tick) {
|
public boolean updateLastSuccessfulInteractionTick(int tick) {
|
||||||
if (lastSuccessfulInteraction != tick) {
|
if (this.lastSuccessfulInteraction != tick) {
|
||||||
lastSuccessfulInteraction = tick;
|
this.lastSuccessfulInteraction = tick;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -231,7 +233,7 @@ public class BukkitServerPlayer extends Player {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int lastSuccessfulInteractionTick() {
|
public int lastSuccessfulInteractionTick() {
|
||||||
return lastSuccessfulInteraction;
|
return this.lastSuccessfulInteraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -283,8 +285,13 @@ public class BukkitServerPlayer extends Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playSound(Key sound, float volume, float pitch) {
|
public void playSound(Key sound, SoundSource source, float volume, float pitch) {
|
||||||
platformPlayer().playSound(platformPlayer(), sound.toString(), SoundCategory.MASTER, volume, pitch);
|
platformPlayer().playSound(platformPlayer(), sound.toString(), SoundUtils.toBukkit(source), volume, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSound(Key sound, BlockPos blockPos, SoundSource source, float volume, float pitch) {
|
||||||
|
platformPlayer().playSound(new Location(null, blockPos.x() + 0.5, blockPos.y() + 0.5, blockPos.z() + 0.5), sound.toString(), SoundUtils.toBukkit(source), volume, pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -535,8 +542,10 @@ public class BukkitServerPlayer extends Player {
|
|||||||
public void abortMiningBlock() {
|
public void abortMiningBlock() {
|
||||||
this.swingHandAck = false;
|
this.swingHandAck = false;
|
||||||
this.miningProgress = 0;
|
this.miningProgress = 0;
|
||||||
if (this.destroyPos != null) {
|
BlockPos pos = this.destroyPos;
|
||||||
this.broadcastDestroyProgress(platformPlayer(), this.destroyPos, LocationUtils.toBlockPos(this.destroyPos), -1);
|
if (pos != null && this.isDestroyingCustomBlock) {
|
||||||
|
// 只纠正自定义方块的
|
||||||
|
this.broadcastDestroyProgress(platformPlayer(), pos, LocationUtils.toBlockPos(pos), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,6 +567,8 @@ public class BukkitServerPlayer extends Player {
|
|||||||
int currentTick = gameTicks();
|
int currentTick = gameTicks();
|
||||||
// optimize break speed, otherwise it would be too fast
|
// optimize break speed, otherwise it would be too fast
|
||||||
if (currentTick - this.lastSuccessfulBreak <= 5) return;
|
if (currentTick - this.lastSuccessfulBreak <= 5) return;
|
||||||
|
Object destroyedState = this.destroyedState;
|
||||||
|
if (destroyedState == null) return;
|
||||||
try {
|
try {
|
||||||
org.bukkit.entity.Player player = platformPlayer();
|
org.bukkit.entity.Player player = platformPlayer();
|
||||||
double range = getCachedInteractionRange();
|
double range = getCachedInteractionRange();
|
||||||
@@ -575,7 +586,7 @@ public class BukkitServerPlayer extends Player {
|
|||||||
|
|
||||||
// send hit sound if the sound is removed
|
// send hit sound if the sound is removed
|
||||||
if (currentTick - this.lastHitBlockTime > 3) {
|
if (currentTick - this.lastHitBlockTime > 3) {
|
||||||
Object blockOwner = FastNMS.INSTANCE.method$BlockState$getBlock(this.destroyedState);
|
Object blockOwner = FastNMS.INSTANCE.method$BlockState$getBlock(destroyedState);
|
||||||
Object soundType = CoreReflections.field$BlockBehaviour$soundType.get(blockOwner);
|
Object soundType = CoreReflections.field$BlockBehaviour$soundType.get(blockOwner);
|
||||||
Object soundEvent = CoreReflections.field$SoundType$hitSound.get(soundType);
|
Object soundEvent = CoreReflections.field$SoundType$hitSound.get(soundType);
|
||||||
Object soundId = FastNMS.INSTANCE.field$SoundEvent$location(soundEvent);
|
Object soundId = FastNMS.INSTANCE.field$SoundEvent$location(soundEvent);
|
||||||
@@ -601,8 +612,8 @@ public class BukkitServerPlayer extends Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float progressToAdd = getDestroyProgress(this.destroyedState, hitPos);
|
float progressToAdd = getDestroyProgress(destroyedState, hitPos);
|
||||||
int id = BlockStateUtils.blockStateToId(this.destroyedState);
|
int id = BlockStateUtils.blockStateToId(destroyedState);
|
||||||
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(id);
|
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(id);
|
||||||
// double check custom block
|
// double check custom block
|
||||||
if (customState != null && !customState.isEmpty()) {
|
if (customState != null && !customState.isEmpty()) {
|
||||||
@@ -612,13 +623,13 @@ public class BukkitServerPlayer extends Player {
|
|||||||
// it's correct on plugin side
|
// it's correct on plugin side
|
||||||
if (blockSettings.isCorrectTool(item.id())) {
|
if (blockSettings.isCorrectTool(item.id())) {
|
||||||
// but not on serverside
|
// but not on serverside
|
||||||
if (!FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), this.destroyedState)) {
|
if (!FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), destroyedState)) {
|
||||||
// we fix the speed
|
// we fix the speed
|
||||||
progressToAdd = progressToAdd * (10f / 3f);
|
progressToAdd = progressToAdd * (10f / 3f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// not a correct tool on plugin side and not a correct tool on serverside
|
// not a correct tool on plugin side and not a correct tool on serverside
|
||||||
if (!blockSettings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), this.destroyedState)) {
|
if (!blockSettings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), destroyedState)) {
|
||||||
progressToAdd = progressToAdd * (10f / 3f) * blockSettings.incorrectToolSpeed();
|
progressToAdd = progressToAdd * (10f / 3f) * blockSettings.incorrectToolSpeed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -681,7 +692,7 @@ public class BukkitServerPlayer extends Player {
|
|||||||
double d1 = (double) hitPos.y() - otherLocation.getY();
|
double d1 = (double) hitPos.y() - otherLocation.getY();
|
||||||
double d2 = (double) hitPos.z() - otherLocation.getZ();
|
double d2 = (double) hitPos.z() - otherLocation.getZ();
|
||||||
if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) {
|
if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) {
|
||||||
this.plugin.networkManager().sendPacket(this.plugin.adapt(other), packet);
|
FastNMS.INSTANCE.sendPacket(FastNMS.INSTANCE.field$Player$connection$connection(FastNMS.INSTANCE.method$CraftPlayer$getHandle(other)), packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -699,16 +710,20 @@ public class BukkitServerPlayer extends Player {
|
|||||||
public void setIsDestroyingBlock(boolean is, boolean custom) {
|
public void setIsDestroyingBlock(boolean is, boolean custom) {
|
||||||
this.miningProgress = 0;
|
this.miningProgress = 0;
|
||||||
this.isDestroyingBlock = is;
|
this.isDestroyingBlock = is;
|
||||||
this.isDestroyingCustomBlock = custom && is;
|
|
||||||
if (is) {
|
if (is) {
|
||||||
this.swingHandAck = true;
|
this.swingHandAck = true;
|
||||||
|
this.isDestroyingCustomBlock = custom;
|
||||||
} else {
|
} else {
|
||||||
this.swingHandAck = false;
|
this.swingHandAck = false;
|
||||||
this.destroyedState = null;
|
this.destroyedState = null;
|
||||||
if (this.destroyPos != null) {
|
if (this.destroyPos != null) {
|
||||||
|
// 只纠正自定义方块的
|
||||||
|
if (this.isDestroyingCustomBlock) {
|
||||||
this.broadcastDestroyProgress(platformPlayer(), this.destroyPos, LocationUtils.toBlockPos(this.destroyPos), -1);
|
this.broadcastDestroyProgress(platformPlayer(), this.destroyPos, LocationUtils.toBlockPos(this.destroyPos), -1);
|
||||||
|
}
|
||||||
this.destroyPos = null;
|
this.destroyPos = null;
|
||||||
}
|
}
|
||||||
|
this.isDestroyingCustomBlock = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class BukkitSoundManager extends AbstractSoundManager {
|
|||||||
protected void registerSongs(Map<Key, JukeboxSong> songs) {
|
protected void registerSongs(Map<Key, JukeboxSong> songs) {
|
||||||
if (songs.isEmpty()) return;
|
if (songs.isEmpty()) return;
|
||||||
try {
|
try {
|
||||||
Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.instance$Registries$JUKEBOX_SONG);;
|
Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.JUKEBOX_SONG);;
|
||||||
unfreezeRegistry(registry);
|
unfreezeRegistry(registry);
|
||||||
for (Map.Entry<Key, JukeboxSong> entry : songs.entrySet()) {
|
for (Map.Entry<Key, JukeboxSong> entry : songs.entrySet()) {
|
||||||
Key id = entry.getKey();
|
Key id = entry.getKey();
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package net.momirealms.craftengine.bukkit.util;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||||
import net.momirealms.craftengine.core.block.*;
|
import net.momirealms.craftengine.core.block.*;
|
||||||
@@ -22,18 +24,26 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class BlockStateUtils {
|
public class BlockStateUtils {
|
||||||
public static final IdentityHashMap<Object, Object> CLIENT_SIDE_NOTE_BLOCKS = new IdentityHashMap<>();
|
public static final IdentityHashMap<Object, Object> CLIENT_SIDE_NOTE_BLOCKS = new IdentityHashMap<>();
|
||||||
private static int vanillaStateSize;
|
private static int vanillaStateSize;
|
||||||
private static boolean hasInit;
|
private static boolean hasInit;
|
||||||
|
public static Map<Object, Integer> IGNITE_ODDS;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public static void init(int size) {
|
public static void init(int size) {
|
||||||
if (hasInit) {
|
if (hasInit) {
|
||||||
throw new IllegalStateException("BlockStateUtils has already been initialized");
|
throw new IllegalStateException("BlockStateUtils has already been initialized");
|
||||||
}
|
}
|
||||||
vanillaStateSize = size;
|
vanillaStateSize = size;
|
||||||
|
try {
|
||||||
|
IGNITE_ODDS = (Map<Object, Integer>) CoreReflections.field$FireBlock$igniteOdds.get(MBlocks.FIRE);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new ReflectionInitException("Failed to initialize instance$FireBlock$igniteOdds", e);
|
||||||
|
}
|
||||||
hasInit = true;
|
hasInit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,4 +258,9 @@ public class BlockStateUtils {
|
|||||||
public static int vanillaStateSize() {
|
public static int vanillaStateSize() {
|
||||||
return vanillaStateSize;
|
return vanillaStateSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isBurnable(Object state) {
|
||||||
|
Object blockOwner = getBlockOwner(state);
|
||||||
|
return IGNITE_ODDS.getOrDefault(blockOwner, 0) > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class BlockTags {
|
|||||||
Object value = CACHE.get(key);
|
Object value = CACHE.get(key);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
try {
|
try {
|
||||||
value = CoreReflections.method$TagKey$create.invoke(null, MRegistries.instance$Registries$BLOCK, KeyUtils.toResourceLocation(key));
|
value = CoreReflections.method$TagKey$create.invoke(null, MRegistries.BLOCK, KeyUtils.toResourceLocation(key));
|
||||||
CACHE.put(key, value);
|
CACHE.put(key, value);
|
||||||
return value;
|
return value;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -2,11 +2,8 @@ package net.momirealms.craftengine.bukkit.util;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public final class BukkitReflectionUtils {
|
public final class BukkitReflectionUtils {
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.util;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.util.DamageSource;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
|
|
||||||
|
public class DamageCauseUtils {
|
||||||
|
|
||||||
|
private DamageCauseUtils() {}
|
||||||
|
|
||||||
|
public static EntityDamageEvent.DamageCause toBukkit(DamageSource cause) {
|
||||||
|
return switch (cause) {
|
||||||
|
case BLOCK_EXPLOSION -> EntityDamageEvent.DamageCause.BLOCK_EXPLOSION;
|
||||||
|
case CAMPFIRE -> EntityDamageEvent.DamageCause.CAMPFIRE;
|
||||||
|
case CONTACT -> EntityDamageEvent.DamageCause.CONTACT;
|
||||||
|
case CRAMMING -> EntityDamageEvent.DamageCause.CRAMMING;
|
||||||
|
case CUSTOM -> EntityDamageEvent.DamageCause.CUSTOM;
|
||||||
|
case DROWNING -> EntityDamageEvent.DamageCause.DROWNING;
|
||||||
|
case DRYOUT -> EntityDamageEvent.DamageCause.DRYOUT;
|
||||||
|
case ENTITY_ATTACK -> EntityDamageEvent.DamageCause.ENTITY_ATTACK;
|
||||||
|
case ENTITY_EXPLOSION -> EntityDamageEvent.DamageCause.ENTITY_EXPLOSION;
|
||||||
|
case ENTITY_SWEEP_ATTACK -> EntityDamageEvent.DamageCause.ENTITY_SWEEP_ATTACK;
|
||||||
|
case FALL -> EntityDamageEvent.DamageCause.FALL;
|
||||||
|
case FALLING_BLOCK -> EntityDamageEvent.DamageCause.FALLING_BLOCK;
|
||||||
|
case FIRE -> EntityDamageEvent.DamageCause.FIRE;
|
||||||
|
case FIRE_TICK -> EntityDamageEvent.DamageCause.FIRE_TICK;
|
||||||
|
case FLY_INTO_WALL -> EntityDamageEvent.DamageCause.FLY_INTO_WALL;
|
||||||
|
case FREEZE -> EntityDamageEvent.DamageCause.FREEZE;
|
||||||
|
case HOT_FLOOR -> EntityDamageEvent.DamageCause.HOT_FLOOR;
|
||||||
|
case KILL -> EntityDamageEvent.DamageCause.KILL;
|
||||||
|
case LAVA -> EntityDamageEvent.DamageCause.LAVA;
|
||||||
|
case LIGHTNING -> EntityDamageEvent.DamageCause.LIGHTNING;
|
||||||
|
case MAGIC -> EntityDamageEvent.DamageCause.MAGIC;
|
||||||
|
case MELTING -> EntityDamageEvent.DamageCause.MELTING;
|
||||||
|
case POISON -> EntityDamageEvent.DamageCause.POISON;
|
||||||
|
case PROJECTILE -> EntityDamageEvent.DamageCause.PROJECTILE;
|
||||||
|
case SONIC_BOOM -> EntityDamageEvent.DamageCause.SONIC_BOOM;
|
||||||
|
case STARVATION -> EntityDamageEvent.DamageCause.STARVATION;
|
||||||
|
case SUFFOCATION -> EntityDamageEvent.DamageCause.SUFFOCATION;
|
||||||
|
case SUICIDE -> EntityDamageEvent.DamageCause.SUICIDE;
|
||||||
|
case THORNS -> EntityDamageEvent.DamageCause.THORNS;
|
||||||
|
case VOID -> EntityDamageEvent.DamageCause.VOID;
|
||||||
|
case WITHER -> EntityDamageEvent.DamageCause.WITHER;
|
||||||
|
case WORLD_BORDER -> EntityDamageEvent.DamageCause.WORLD_BORDER;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DamageSource fromBukkit(EntityDamageEvent.DamageCause cause) {
|
||||||
|
return switch (cause) {
|
||||||
|
case BLOCK_EXPLOSION -> DamageSource.BLOCK_EXPLOSION;
|
||||||
|
case CAMPFIRE -> DamageSource.CAMPFIRE;
|
||||||
|
case CONTACT -> DamageSource.CONTACT;
|
||||||
|
case CRAMMING -> DamageSource.CRAMMING;
|
||||||
|
case CUSTOM -> DamageSource.CUSTOM;
|
||||||
|
case DROWNING -> DamageSource.DROWNING;
|
||||||
|
case DRYOUT -> DamageSource.DRYOUT;
|
||||||
|
case ENTITY_ATTACK -> DamageSource.ENTITY_ATTACK;
|
||||||
|
case ENTITY_EXPLOSION -> DamageSource.ENTITY_EXPLOSION;
|
||||||
|
case ENTITY_SWEEP_ATTACK -> DamageSource.ENTITY_SWEEP_ATTACK;
|
||||||
|
case FALL -> DamageSource.FALL;
|
||||||
|
case FALLING_BLOCK -> DamageSource.FALLING_BLOCK;
|
||||||
|
case FIRE -> DamageSource.FIRE;
|
||||||
|
case FIRE_TICK -> DamageSource.FIRE_TICK;
|
||||||
|
case FLY_INTO_WALL -> DamageSource.FLY_INTO_WALL;
|
||||||
|
case FREEZE -> DamageSource.FREEZE;
|
||||||
|
case HOT_FLOOR -> DamageSource.HOT_FLOOR;
|
||||||
|
case KILL -> DamageSource.KILL;
|
||||||
|
case LAVA -> DamageSource.LAVA;
|
||||||
|
case LIGHTNING -> DamageSource.LIGHTNING;
|
||||||
|
case MAGIC -> DamageSource.MAGIC;
|
||||||
|
case MELTING -> DamageSource.MELTING;
|
||||||
|
case POISON -> DamageSource.POISON;
|
||||||
|
case PROJECTILE -> DamageSource.PROJECTILE;
|
||||||
|
case SONIC_BOOM -> DamageSource.SONIC_BOOM;
|
||||||
|
case STARVATION -> DamageSource.STARVATION;
|
||||||
|
case SUFFOCATION -> DamageSource.SUFFOCATION;
|
||||||
|
case SUICIDE -> DamageSource.SUICIDE;
|
||||||
|
case THORNS -> DamageSource.THORNS;
|
||||||
|
case VOID -> DamageSource.VOID;
|
||||||
|
case WITHER -> DamageSource.WITHER;
|
||||||
|
case WORLD_BORDER -> DamageSource.WORLD_BORDER;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ public class FeatureUtils {
|
|||||||
|
|
||||||
public static Object createFeatureKey(Key id) {
|
public static Object createFeatureKey(Key id) {
|
||||||
try {
|
try {
|
||||||
return CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.instance$Registries$CONFIGURED_FEATURE, KeyUtils.toResourceLocation(id));
|
return CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.CONFIGURED_FEATURE, KeyUtils.toResourceLocation(id));
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ public class InteractUtils {
|
|||||||
keyReference, item.getItem()
|
keyReference, item.getItem()
|
||||||
))) != null).isPresent();
|
))) != null).isPresent();
|
||||||
});
|
});
|
||||||
|
registerInteraction(BlockKeys.DECORATED_POT, (player, item, blockState, result) -> true);
|
||||||
registerInteraction(BlockKeys.HOPPER, (player, item, blockState, result) -> true);
|
registerInteraction(BlockKeys.HOPPER, (player, item, blockState, result) -> true);
|
||||||
registerInteraction(BlockKeys.DISPENSER, (player, item, blockState, result) -> true);
|
registerInteraction(BlockKeys.DISPENSER, (player, item, blockState, result) -> true);
|
||||||
registerInteraction(BlockKeys.DROPPER, (player, item, blockState, result) -> true);
|
registerInteraction(BlockKeys.DROPPER, (player, item, blockState, result) -> true);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class ItemTags {
|
|||||||
Object value = CACHE.get(key);
|
Object value = CACHE.get(key);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
try {
|
try {
|
||||||
value = CoreReflections.method$TagKey$create.invoke(null, MRegistries.instance$Registries$ITEM, KeyUtils.toResourceLocation(key));
|
value = CoreReflections.method$TagKey$create.invoke(null, MRegistries.ITEM, KeyUtils.toResourceLocation(key));
|
||||||
CACHE.put(key, value);
|
CACHE.put(key, value);
|
||||||
return value;
|
return value;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
package net.momirealms.craftengine.bukkit.util;
|
package net.momirealms.craftengine.bukkit.util;
|
||||||
|
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
|
||||||
|
|
||||||
public class NoteBlockChainUpdateUtils {
|
public class NoteBlockChainUpdateUtils {
|
||||||
|
|
||||||
private NoteBlockChainUpdateUtils() {}
|
private NoteBlockChainUpdateUtils() {}
|
||||||
|
|
||||||
|
// TODO 都在一个区块内,应该优化到区块内的方块getter
|
||||||
public static void noteBlockChainUpdate(Object level, Object chunkSource, Object direction, Object blockPos, int times) {
|
public static void noteBlockChainUpdate(Object level, Object chunkSource, Object direction, Object blockPos, int times) {
|
||||||
if (times >= Config.maxChainUpdate()) return;
|
if (times-- < 0) return;
|
||||||
Object relativePos = FastNMS.INSTANCE.method$BlockPos$relative(blockPos, direction);
|
Object relativePos = FastNMS.INSTANCE.method$BlockPos$relative(blockPos, direction);
|
||||||
Object state = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, relativePos);
|
Object state = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, relativePos);
|
||||||
if (BlockStateUtils.isClientSideNoteBlock(state)) {
|
if (BlockStateUtils.isClientSideNoteBlock(state)) {
|
||||||
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, relativePos);
|
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, relativePos);
|
||||||
noteBlockChainUpdate(level, chunkSource, direction, relativePos, times+1);
|
noteBlockChainUpdate(level, chunkSource, direction, relativePos, times);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class RegistryUtils {
|
|||||||
|
|
||||||
public static int currentBiomeRegistrySize() {
|
public static int currentBiomeRegistrySize() {
|
||||||
try {
|
try {
|
||||||
Object idMap = CoreReflections.method$Registry$asHolderIdMap.invoke(CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.instance$Registries$BIOME));
|
Object idMap = CoreReflections.method$Registry$asHolderIdMap.invoke(CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.BIOME));
|
||||||
return (int) CoreReflections.method$IdMap$size.invoke(idMap);
|
return (int) CoreReflections.method$IdMap$size.invoke(idMap);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|||||||
@@ -1,20 +1,14 @@
|
|||||||
package net.momirealms.craftengine.bukkit.world;
|
package net.momirealms.craftengine.bukkit.world;
|
||||||
|
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
import net.momirealms.craftengine.bukkit.util.*;
|
||||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
|
||||||
import net.momirealms.craftengine.bukkit.util.ParticleUtils;
|
|
||||||
import net.momirealms.craftengine.bukkit.util.SoundUtils;
|
|
||||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||||
import net.momirealms.craftengine.core.item.Item;
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||||
import net.momirealms.craftengine.core.sound.SoundSource;
|
import net.momirealms.craftengine.core.sound.SoundSource;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
import net.momirealms.craftengine.core.world.BlockInWorld;
|
import net.momirealms.craftengine.core.world.*;
|
||||||
import net.momirealms.craftengine.core.world.Position;
|
|
||||||
import net.momirealms.craftengine.core.world.World;
|
|
||||||
import net.momirealms.craftengine.core.world.WorldHeight;
|
|
||||||
import net.momirealms.craftengine.core.world.particle.ParticleData;
|
import net.momirealms.craftengine.core.world.particle.ParticleData;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
@@ -124,4 +118,9 @@ public class BukkitWorld implements World {
|
|||||||
Object blockPos = FastNMS.INSTANCE.constructor$BlockPos(x, y, z);
|
Object blockPos = FastNMS.INSTANCE.constructor$BlockPos(x, y, z);
|
||||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(worldServer, blockPos, blockState.handle(), flags);
|
FastNMS.INSTANCE.method$LevelWriter$setBlock(worldServer, blockPos, blockState.handle(), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void levelEvent(int id, BlockPos pos, int data) {
|
||||||
|
FastNMS.INSTANCE.method$Level$levelEvent(serverWorld(), id, LocationUtils.toBlockPos(pos), data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,6 +182,20 @@ debug_clear_cooldown:
|
|||||||
- /craftengine debug clear-cooldown
|
- /craftengine debug clear-cooldown
|
||||||
- /ce debug clear-cooldown
|
- /ce debug clear-cooldown
|
||||||
|
|
||||||
|
debug_entity_id_to_uuid:
|
||||||
|
enable: true
|
||||||
|
permission: ce.command.debug.entity_id_to_uuid
|
||||||
|
usage:
|
||||||
|
- /craftengine debug entity-id-to-uuid
|
||||||
|
- /ce debug entity-id-to-uuid
|
||||||
|
|
||||||
|
debug_migrate_templates:
|
||||||
|
enable: true
|
||||||
|
permission: ce.command.debug.migrate_templates
|
||||||
|
usage:
|
||||||
|
- /craftengine debug migrate-templates
|
||||||
|
- /ce debug migrate-templates
|
||||||
|
|
||||||
debug_test:
|
debug_test:
|
||||||
enable: true
|
enable: true
|
||||||
permission: ce.command.debug.test
|
permission: ce.command.debug.test
|
||||||
|
|||||||
@@ -49,12 +49,14 @@ resource-pack:
|
|||||||
bypass-textures:
|
bypass-textures:
|
||||||
# - minecraft:block/farmland
|
# - minecraft:block/farmland
|
||||||
- "@legacy_unicode"
|
- "@legacy_unicode"
|
||||||
- "@vanilla_font_textures"
|
- "@vanilla_textures"
|
||||||
- "@vanilla_item_textures"
|
bypass-models:
|
||||||
- "@vanilla_block_textures"
|
- "@vanilla_models"
|
||||||
bypass-models: []
|
|
||||||
bypass-sounds: []
|
bypass-sounds: []
|
||||||
bypass-equipments: []
|
bypass-equipments: []
|
||||||
|
# Validate if there are any errors in the resource pack, such as missing textures or models
|
||||||
|
validate:
|
||||||
|
enable: true
|
||||||
supported-version:
|
supported-version:
|
||||||
min: "1.20"
|
min: "1.20"
|
||||||
max: LATEST
|
max: LATEST
|
||||||
@@ -336,7 +338,7 @@ gui:
|
|||||||
|
|
||||||
performance:
|
performance:
|
||||||
# Maximum chain update depth when fixing client visuals
|
# Maximum chain update depth when fixing client visuals
|
||||||
max-block-chain-update-limit: 64
|
max-note-block-chain-update-limit: 48
|
||||||
# Prevent lag or oversized packet when processing emoji-heavy content
|
# Prevent lag or oversized packet when processing emoji-heavy content
|
||||||
max-emojis-per-parse: 16
|
max-emojis-per-parse: 16
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -12,7 +12,7 @@ minecraft:jungle_sapling[stage=1]: minecraft:jungle_sapling[stage=0]
|
|||||||
minecraft:dark_oak_sapling[stage=1]: minecraft:dark_oak_sapling[stage=0]
|
minecraft:dark_oak_sapling[stage=1]: minecraft:dark_oak_sapling[stage=0]
|
||||||
minecraft:acacia_sapling[stage=1]: minecraft:acacia_sapling[stage=0]
|
minecraft:acacia_sapling[stage=1]: minecraft:acacia_sapling[stage=0]
|
||||||
minecraft:cherry_sapling[stage=1]: minecraft:cherry_sapling[stage=0]
|
minecraft:cherry_sapling[stage=1]: minecraft:cherry_sapling[stage=0]
|
||||||
#minecraft:pale_oak_leaves[stage=1]: minecraft:pale_oak_leaves[stage=0] # 1.21.4+
|
#minecraft:pale_oak_sapling[stage=1]: minecraft:pale_oak_sapling[stage=0] # 1.21.4+
|
||||||
########################################################################################################################################################################################################################
|
########################################################################################################################################################################################################################
|
||||||
# Ideal block for lower half slabs
|
# Ideal block for lower half slabs
|
||||||
# Sculk Sensor
|
# Sculk Sensor
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ items#misc:
|
|||||||
template: "default:loot_table/self"
|
template: "default:loot_table/self"
|
||||||
settings:
|
settings:
|
||||||
template:
|
template:
|
||||||
- default:sound/sand
|
- default:sound/stone
|
||||||
- default:pickaxe_power/level_1
|
- default:pickaxe_power/level_1
|
||||||
- default:settings/solid_1x1x1
|
- default:settings/solid_1x1x1
|
||||||
overrides:
|
overrides:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ templates:
|
|||||||
default:emoji/basic:
|
default:emoji/basic:
|
||||||
content: "<hover:show_text:'<i18n:emoji.tip>'><!shadow><white><arg:emoji></white></!shadow></hover>"
|
content: "<hover:show_text:'<i18n:emoji.tip>'><!shadow><white><arg:emoji></white></!shadow></hover>"
|
||||||
default:emoji/addition_info:
|
default:emoji/addition_info:
|
||||||
content: "<hover:show_text:'<i18n:emoji.tip>'><!shadow><white><arg:emoji></white></!shadow>{text}</hover>"
|
content: "<hover:show_text:'<i18n:emoji.tip>'><!shadow><white><arg:emoji></white></!shadow>${text}</hover>"
|
||||||
|
|
||||||
emoji:
|
emoji:
|
||||||
default:emoji_location:
|
default:emoji_location:
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
items:
|
items:
|
||||||
# client-bound-data requires CraftEngine mod to apply
|
|
||||||
minecraft:string:
|
minecraft:string:
|
||||||
client-bound-data:
|
client-bound-data:
|
||||||
components:
|
components:
|
||||||
|
|||||||
@@ -229,16 +229,16 @@ items#topaz_gears:
|
|||||||
|
|
||||||
templates:
|
templates:
|
||||||
default:armor/topaz:
|
default:armor/topaz:
|
||||||
material: "chainmail_{part}"
|
material: "chainmail_${part}"
|
||||||
custom-model-data: 1000
|
custom-model-data: 1000
|
||||||
data:
|
data:
|
||||||
item-name: "<!i><#FF8C00><i18n:item.topaz_{part}>"
|
item-name: "<!i><#FF8C00><i18n:item.topaz_${part}>"
|
||||||
tooltip-style: minecraft:topaz
|
tooltip-style: minecraft:topaz
|
||||||
settings:
|
settings:
|
||||||
tags:
|
tags:
|
||||||
- "default:topaz_tools"
|
- "default:topaz_tools"
|
||||||
equippable:
|
equippable:
|
||||||
slot: "{slot}"
|
slot: "${slot}"
|
||||||
asset-id: topaz
|
asset-id: topaz
|
||||||
humanoid: "minecraft:topaz"
|
humanoid: "minecraft:topaz"
|
||||||
humanoid-leggings: "minecraft:topaz"
|
humanoid-leggings: "minecraft:topaz"
|
||||||
@@ -247,111 +247,111 @@ templates:
|
|||||||
property: minecraft:trim_material
|
property: minecraft:trim_material
|
||||||
fallback:
|
fallback:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}"
|
path: "minecraft:item/custom/topaz_${part}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
cases:
|
cases:
|
||||||
- when: minecraft:quartz
|
- when: minecraft:quartz
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_quartz_trim"
|
path: "minecraft:item/custom/topaz_${part}_quartz_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_quartz"
|
"layer1": "minecraft:trims/items/${part}_trim_quartz"
|
||||||
- when: minecraft:iron
|
- when: minecraft:iron
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_iron_trim"
|
path: "minecraft:item/custom/topaz_${part}_iron_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_iron"
|
"layer1": "minecraft:trims/items/${part}_trim_iron"
|
||||||
- when: minecraft:netherite
|
- when: minecraft:netherite
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_netherite_trim"
|
path: "minecraft:item/custom/topaz_${part}_netherite_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_netherite"
|
"layer1": "minecraft:trims/items/${part}_trim_netherite"
|
||||||
- when: minecraft:redstone
|
- when: minecraft:redstone
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_redstone_trim"
|
path: "minecraft:item/custom/topaz_${part}_redstone_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_redstone"
|
"layer1": "minecraft:trims/items/${part}_trim_redstone"
|
||||||
- when: minecraft:copper
|
- when: minecraft:copper
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_copper_trim"
|
path: "minecraft:item/custom/topaz_${part}_copper_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_copper"
|
"layer1": "minecraft:trims/items/${part}_trim_copper"
|
||||||
- when: minecraft:gold
|
- when: minecraft:gold
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_gold_trim"
|
path: "minecraft:item/custom/topaz_${part}_gold_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_gold"
|
"layer1": "minecraft:trims/items/${part}_trim_gold"
|
||||||
- when: minecraft:emerald
|
- when: minecraft:emerald
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_emerald_trim"
|
path: "minecraft:item/custom/topaz_${part}_emerald_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_emerald"
|
"layer1": "minecraft:trims/items/${part}_trim_emerald"
|
||||||
- when: minecraft:diamond
|
- when: minecraft:diamond
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_diamond_trim"
|
path: "minecraft:item/custom/topaz_${part}_diamond_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_diamond"
|
"layer1": "minecraft:trims/items/${part}_trim_diamond"
|
||||||
- when: minecraft:lapis
|
- when: minecraft:lapis
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_lapis_trim"
|
path: "minecraft:item/custom/topaz_${part}_lapis_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_lapis"
|
"layer1": "minecraft:trims/items/${part}_trim_lapis"
|
||||||
- when: minecraft:amethyst
|
- when: minecraft:amethyst
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_amethyst_trim"
|
path: "minecraft:item/custom/topaz_${part}_amethyst_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_amethyst"
|
"layer1": "minecraft:trims/items/${part}_trim_amethyst"
|
||||||
- when: minecraft:resin
|
- when: minecraft:resin
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "minecraft:item/custom/topaz_{part}_resin_trim"
|
path: "minecraft:item/custom/topaz_${part}_resin_trim"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "minecraft:item/custom/topaz_{part}"
|
"layer0": "minecraft:item/custom/topaz_${part}"
|
||||||
"layer1": "minecraft:trims/items/{part}_trim_resin"
|
"layer1": "minecraft:trims/items/${part}_trim_resin"
|
||||||
|
|
||||||
recipes#11:
|
recipes#11:
|
||||||
default:topaz_shovel:
|
default:topaz_shovel:
|
||||||
|
|||||||
@@ -7,32 +7,32 @@ templates#models#block:
|
|||||||
# model: model_path
|
# model: model_path
|
||||||
# texture: texture_path
|
# texture: texture_path
|
||||||
default:model/cube_all:
|
default:model/cube_all:
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:block/cube_all"
|
parent: "minecraft:block/cube_all"
|
||||||
textures:
|
textures:
|
||||||
"all": "{texture}"
|
"all": "${texture}"
|
||||||
# template: default:model/simplified_cube_all
|
# template: default:model/simplified_cube_all
|
||||||
# arguments:
|
# arguments:
|
||||||
# path: [model/texture]_path
|
# path: [model/texture]_path
|
||||||
default:model/simplified_cube_all:
|
default:model/simplified_cube_all:
|
||||||
path: "{path}"
|
path: "${path}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:block/cube_all"
|
parent: "minecraft:block/cube_all"
|
||||||
textures:
|
textures:
|
||||||
"all": "{path}"
|
"all": "${path}"
|
||||||
# template: default:model/cube_column
|
# template: default:model/cube_column
|
||||||
# arguments:
|
# arguments:
|
||||||
# model: model_path
|
# model: model_path
|
||||||
# end_texture: end_texture_path
|
# end_texture: end_texture_path
|
||||||
# side_texture: side_texture_path
|
# side_texture: side_texture_path
|
||||||
default:model/cube_column:
|
default:model/cube_column:
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:block/cube_column"
|
parent: "minecraft:block/cube_column"
|
||||||
textures:
|
textures:
|
||||||
"end": "{end_texture}"
|
"end": "${end_texture}"
|
||||||
"side": "{side_texture}"
|
"side": "${side_texture}"
|
||||||
# template: default:model/cube
|
# template: default:model/cube
|
||||||
# arguments:
|
# arguments:
|
||||||
# model: model_path
|
# model: model_path
|
||||||
@@ -44,7 +44,7 @@ templates#models#block:
|
|||||||
# south_texture: south_texture_path
|
# south_texture: south_texture_path
|
||||||
# west_texture: west_texture_path
|
# west_texture: west_texture_path
|
||||||
default:model/cube:
|
default:model/cube:
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:block/cube_column"
|
parent: "minecraft:block/cube_column"
|
||||||
textures:
|
textures:
|
||||||
@@ -64,21 +64,21 @@ templates#models#2d:
|
|||||||
# texture: texture_path
|
# texture: texture_path
|
||||||
default:model/generated:
|
default:model/generated:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{texture}"
|
"layer0": "${texture}"
|
||||||
# template: default:model/simplified_generated
|
# template: default:model/simplified_generated
|
||||||
# arguments:
|
# arguments:
|
||||||
# path: [model/texture]_path
|
# path: [model/texture]_path
|
||||||
default:model/simplified_generated:
|
default:model/simplified_generated:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{path}"
|
path: "${path}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{path}"
|
"layer0": "${path}"
|
||||||
# template: default:model/2_layer_generated
|
# template: default:model/2_layer_generated
|
||||||
# arguments:
|
# arguments:
|
||||||
# model: model_path
|
# model: model_path
|
||||||
@@ -86,33 +86,33 @@ templates#models#2d:
|
|||||||
# layer1: texture_path
|
# layer1: texture_path
|
||||||
default:model/2_layer_generated:
|
default:model/2_layer_generated:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{layer0}"
|
"layer0": "${layer0}"
|
||||||
"layer1": "{layer1}"
|
"layer1": "${layer1}"
|
||||||
# template: default:model/handheld
|
# template: default:model/handheld
|
||||||
# arguments:
|
# arguments:
|
||||||
# model: model_path
|
# model: model_path
|
||||||
# texture: texture_path
|
# texture: texture_path
|
||||||
default:model/handheld:
|
default:model/handheld:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/handheld"
|
parent: "minecraft:item/handheld"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{texture}"
|
"layer0": "${texture}"
|
||||||
# template: default:model/simplified_handheld
|
# template: default:model/simplified_handheld
|
||||||
# arguments:
|
# arguments:
|
||||||
# path: [model/texture]_path
|
# path: [model/texture]_path
|
||||||
default:model/simplified_handheld:
|
default:model/simplified_handheld:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{path}"
|
path: "${path}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/handheld"
|
parent: "minecraft:item/handheld"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{path}"
|
"layer0": "${path}"
|
||||||
# template: default:model/elytra
|
# template: default:model/elytra
|
||||||
# arguments:
|
# arguments:
|
||||||
# model: model_path
|
# model: model_path
|
||||||
@@ -123,17 +123,17 @@ templates#models#2d:
|
|||||||
type: "minecraft:condition"
|
type: "minecraft:condition"
|
||||||
property: minecraft:broken
|
property: minecraft:broken
|
||||||
on-false:
|
on-false:
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{texture}"
|
"layer0": "${texture}"
|
||||||
on-true:
|
on-true:
|
||||||
path: "{broken_model}"
|
path: "${broken_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{broken_texture}"
|
"layer0": "${broken_texture}"
|
||||||
# template: default:model/simplified_elytra
|
# template: default:model/simplified_elytra
|
||||||
# arguments:
|
# arguments:
|
||||||
# path: [model/texture]_path
|
# path: [model/texture]_path
|
||||||
@@ -141,10 +141,10 @@ templates#models#2d:
|
|||||||
default:model/simplified_elytra:
|
default:model/simplified_elytra:
|
||||||
template: default:model/elytra
|
template: default:model/elytra
|
||||||
arguments:
|
arguments:
|
||||||
model: "{path}"
|
model: "${path}"
|
||||||
texture: "{path}"
|
texture: "${path}"
|
||||||
broken_model: "{broken_path}"
|
broken_model: "${broken_path}"
|
||||||
broken_texture: "{broken_path}"
|
broken_texture: "${broken_path}"
|
||||||
|
|
||||||
# shield
|
# shield
|
||||||
templates#models#shield:
|
templates#models#shield:
|
||||||
@@ -157,10 +157,10 @@ templates#models#shield:
|
|||||||
property: "minecraft:using_item"
|
property: "minecraft:using_item"
|
||||||
on-false:
|
on-false:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
on-true:
|
on-true:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{block_model}"
|
path: "${block_model}"
|
||||||
|
|
||||||
# fishing rods
|
# fishing rods
|
||||||
templates#models#fishing_rod:
|
templates#models#fishing_rod:
|
||||||
@@ -173,10 +173,10 @@ templates#models#fishing_rod:
|
|||||||
property: "minecraft:fishing_rod/cast"
|
property: "minecraft:fishing_rod/cast"
|
||||||
on-false:
|
on-false:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
on-true:
|
on-true:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{cast_model}"
|
path: "${cast_model}"
|
||||||
# template: default:model/fishing_rod_2d
|
# template: default:model/fishing_rod_2d
|
||||||
# arguments:
|
# arguments:
|
||||||
# model: rod_model_path
|
# model: rod_model_path
|
||||||
@@ -188,18 +188,18 @@ templates#models#fishing_rod:
|
|||||||
property: "minecraft:fishing_rod/cast"
|
property: "minecraft:fishing_rod/cast"
|
||||||
on-false:
|
on-false:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/fishing_rod"
|
parent: "minecraft:item/fishing_rod"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{texture}"
|
"layer0": "${texture}"
|
||||||
on-true:
|
on-true:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{cast_model}"
|
path: "${cast_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/fishing_rod"
|
parent: "minecraft:item/fishing_rod"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{cast_texture}"
|
"layer0": "${cast_texture}"
|
||||||
# template: default:model/simplified_fishing_rod_2d
|
# template: default:model/simplified_fishing_rod_2d
|
||||||
# arguments:
|
# arguments:
|
||||||
# path: rod_[model/texture]_path
|
# path: rod_[model/texture]_path
|
||||||
@@ -207,10 +207,10 @@ templates#models#fishing_rod:
|
|||||||
default:model/simplified_fishing_rod_2d:
|
default:model/simplified_fishing_rod_2d:
|
||||||
template: default:model/fishing_rod_2d
|
template: default:model/fishing_rod_2d
|
||||||
arguments:
|
arguments:
|
||||||
texture: "{path}"
|
texture: "${path}"
|
||||||
model: "{path}"
|
model: "${path}"
|
||||||
cast_texture: "{cast_path}"
|
cast_texture: "${cast_path}"
|
||||||
cast_model: "{cast_path}"
|
cast_model: "${cast_path}"
|
||||||
|
|
||||||
# bows
|
# bows
|
||||||
templates#models#bow:
|
templates#models#bow:
|
||||||
@@ -225,7 +225,7 @@ templates#models#bow:
|
|||||||
property: "minecraft:using_item"
|
property: "minecraft:using_item"
|
||||||
on-false:
|
on-false:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
on-true:
|
on-true:
|
||||||
type: "minecraft:range_dispatch"
|
type: "minecraft:range_dispatch"
|
||||||
property: "minecraft:use_duration"
|
property: "minecraft:use_duration"
|
||||||
@@ -233,15 +233,15 @@ templates#models#bow:
|
|||||||
entries:
|
entries:
|
||||||
- model:
|
- model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_1_model}"
|
path: "${pulling_1_model}"
|
||||||
threshold: 0.65
|
threshold: 0.65
|
||||||
- model:
|
- model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_2_model}"
|
path: "${pulling_2_model}"
|
||||||
threshold: 0.9
|
threshold: 0.9
|
||||||
fallback:
|
fallback:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_0_model}"
|
path: "${pulling_0_model}"
|
||||||
# template: default:model/bow_2d
|
# template: default:model/bow_2d
|
||||||
# arguments:
|
# arguments:
|
||||||
# model: bow_model_path
|
# model: bow_model_path
|
||||||
@@ -257,11 +257,11 @@ templates#models#bow:
|
|||||||
property: "minecraft:using_item"
|
property: "minecraft:using_item"
|
||||||
on-false:
|
on-false:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/bow"
|
parent: "minecraft:item/bow"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{texture}"
|
"layer0": "${texture}"
|
||||||
on-true:
|
on-true:
|
||||||
type: "minecraft:range_dispatch"
|
type: "minecraft:range_dispatch"
|
||||||
property: "minecraft:use_duration"
|
property: "minecraft:use_duration"
|
||||||
@@ -269,27 +269,27 @@ templates#models#bow:
|
|||||||
entries:
|
entries:
|
||||||
- model:
|
- model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_1_model}"
|
path: "${pulling_1_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/bow_pulling_1"
|
parent: "minecraft:item/bow_pulling_1"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{pulling_1_texture}"
|
"layer0": "${pulling_1_texture}"
|
||||||
threshold: 0.65
|
threshold: 0.65
|
||||||
- model:
|
- model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_2_model}"
|
path: "${pulling_2_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/bow_pulling_2"
|
parent: "minecraft:item/bow_pulling_2"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{pulling_2_texture}"
|
"layer0": "${pulling_2_texture}"
|
||||||
threshold: 0.9
|
threshold: 0.9
|
||||||
fallback:
|
fallback:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_0_model}"
|
path: "${pulling_0_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/bow_pulling_0"
|
parent: "minecraft:item/bow_pulling_0"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{pulling_0_texture}"
|
"layer0": "${pulling_0_texture}"
|
||||||
# template: default:model/simplified_bow_2d
|
# template: default:model/simplified_bow_2d
|
||||||
# arguments:
|
# arguments:
|
||||||
# path: bow_[model/texture]_path
|
# path: bow_[model/texture]_path
|
||||||
@@ -299,14 +299,14 @@ templates#models#bow:
|
|||||||
default:model/simplified_bow_2d:
|
default:model/simplified_bow_2d:
|
||||||
template: default:model/bow_2d
|
template: default:model/bow_2d
|
||||||
arguments:
|
arguments:
|
||||||
model: "{path}"
|
model: "${path}"
|
||||||
pulling_0_model: "{pulling_0_path}"
|
pulling_0_model: "${pulling_0_path}"
|
||||||
pulling_1_model: "{pulling_1_path}"
|
pulling_1_model: "${pulling_1_path}"
|
||||||
pulling_2_model: "{pulling_2_path}"
|
pulling_2_model: "${pulling_2_path}"
|
||||||
texture: "{path}"
|
texture: "${path}"
|
||||||
pulling_0_texture: "{pulling_0_path}"
|
pulling_0_texture: "${pulling_0_path}"
|
||||||
pulling_1_texture: "{pulling_1_path}"
|
pulling_1_texture: "${pulling_1_path}"
|
||||||
pulling_2_texture: "{pulling_2_path}"
|
pulling_2_texture: "${pulling_2_path}"
|
||||||
|
|
||||||
# crossbows
|
# crossbows
|
||||||
templates#models#crossbow:
|
templates#models#crossbow:
|
||||||
@@ -328,29 +328,29 @@ templates#models#crossbow:
|
|||||||
- when: arrow
|
- when: arrow
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{arrow_model}"
|
path: "${arrow_model}"
|
||||||
- when: rocket
|
- when: rocket
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{firework_model}"
|
path: "${firework_model}"
|
||||||
fallback:
|
fallback:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
on-true:
|
on-true:
|
||||||
type: "minecraft:range_dispatch"
|
type: "minecraft:range_dispatch"
|
||||||
property: "minecraft:crossbow/pull"
|
property: "minecraft:crossbow/pull"
|
||||||
entries:
|
entries:
|
||||||
- model:
|
- model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_1_model}"
|
path: "${pulling_1_model}"
|
||||||
threshold: 0.58
|
threshold: 0.58
|
||||||
- model:
|
- model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_2_model}"
|
path: "${pulling_2_model}"
|
||||||
threshold: 1.0
|
threshold: 1.0
|
||||||
fallback:
|
fallback:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_0_model}"
|
path: "${pulling_0_model}"
|
||||||
# template: default:model/crossbow_2d
|
# template: default:model/crossbow_2d
|
||||||
# arguments:
|
# arguments:
|
||||||
# model: crossbow_model_path
|
# model: crossbow_model_path
|
||||||
@@ -375,53 +375,53 @@ templates#models#crossbow:
|
|||||||
- when: arrow
|
- when: arrow
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{arrow_model}"
|
path: "${arrow_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/crossbow_arrow"
|
parent: "minecraft:item/crossbow_arrow"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{arrow_texture}"
|
"layer0": "${arrow_texture}"
|
||||||
- when: rocket
|
- when: rocket
|
||||||
model:
|
model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{firework_model}"
|
path: "${firework_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/crossbow_firework"
|
parent: "minecraft:item/crossbow_firework"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{firework_texture}"
|
"layer0": "${firework_texture}"
|
||||||
fallback:
|
fallback:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{model}"
|
path: "${model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/crossbow"
|
parent: "minecraft:item/crossbow"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{texture}"
|
"layer0": "${texture}"
|
||||||
on-true:
|
on-true:
|
||||||
type: "minecraft:range_dispatch"
|
type: "minecraft:range_dispatch"
|
||||||
property: "minecraft:crossbow/pull"
|
property: "minecraft:crossbow/pull"
|
||||||
entries:
|
entries:
|
||||||
- model:
|
- model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_1_model}"
|
path: "${pulling_1_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/crossbow_pulling_1"
|
parent: "minecraft:item/crossbow_pulling_1"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{pulling_1_texture}"
|
"layer0": "${pulling_1_texture}"
|
||||||
threshold: 0.58
|
threshold: 0.58
|
||||||
- model:
|
- model:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_2_model}"
|
path: "${pulling_2_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/crossbow_pulling_2"
|
parent: "minecraft:item/crossbow_pulling_2"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{pulling_2_texture}"
|
"layer0": "${pulling_2_texture}"
|
||||||
threshold: 1.0
|
threshold: 1.0
|
||||||
fallback:
|
fallback:
|
||||||
type: minecraft:model
|
type: minecraft:model
|
||||||
path: "{pulling_0_model}"
|
path: "${pulling_0_model}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/crossbow_pulling_0"
|
parent: "minecraft:item/crossbow_pulling_0"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{pulling_0_texture}"
|
"layer0": "${pulling_0_texture}"
|
||||||
# template: default:model/simplified_crossbow_2d
|
# template: default:model/simplified_crossbow_2d
|
||||||
# arguments:
|
# arguments:
|
||||||
# path: crossbow_[model/texture]_path
|
# path: crossbow_[model/texture]_path
|
||||||
@@ -433,28 +433,28 @@ templates#models#crossbow:
|
|||||||
default:model/simplified_crossbow_2d:
|
default:model/simplified_crossbow_2d:
|
||||||
template: default:model/crossbow_2d
|
template: default:model/crossbow_2d
|
||||||
arguments:
|
arguments:
|
||||||
model: "{path}"
|
model: "${path}"
|
||||||
texture: "{path}"
|
texture: "${path}"
|
||||||
arrow_model: "{arrow_path}"
|
arrow_model: "${arrow_path}"
|
||||||
arrow_texture: "{arrow_path}"
|
arrow_texture: "${arrow_path}"
|
||||||
firework_model: "{firework_path}"
|
firework_model: "${firework_path}"
|
||||||
firework_texture: "{firework_path}"
|
firework_texture: "${firework_path}"
|
||||||
pulling_0_model: "{pulling_0_path}"
|
pulling_0_model: "${pulling_0_path}"
|
||||||
pulling_0_texture: "{pulling_0_path}"
|
pulling_0_texture: "${pulling_0_path}"
|
||||||
pulling_1_model: "{pulling_1_path}"
|
pulling_1_model: "${pulling_1_path}"
|
||||||
pulling_1_texture: "{pulling_1_path}"
|
pulling_1_texture: "${pulling_1_path}"
|
||||||
pulling_2_model: "{pulling_2_path}"
|
pulling_2_model: "${pulling_2_path}"
|
||||||
pulling_2_texture: "{pulling_2_path}"
|
pulling_2_texture: "${pulling_2_path}"
|
||||||
|
|
||||||
# sounds
|
# sounds
|
||||||
templates#settings#sounds:
|
templates#settings#sounds:
|
||||||
default:sound/block_template:
|
default:sound/block_template:
|
||||||
sounds:
|
sounds:
|
||||||
break: "minecraft:block.{block_type}.break"
|
break: "minecraft:block.${block_type}.break"
|
||||||
step: "minecraft:block.{block_type}.step"
|
step: "minecraft:block.${block_type}.step"
|
||||||
place: "minecraft:block.{block_type}.place"
|
place: "minecraft:block.${block_type}.place"
|
||||||
hit: "minecraft:block.{block_type}.hit"
|
hit: "minecraft:block.${block_type}.hit"
|
||||||
fall: "minecraft:block.{block_type}.fall"
|
fall: "minecraft:block.${block_type}.fall"
|
||||||
default:sound/crop:
|
default:sound/crop:
|
||||||
sounds:
|
sounds:
|
||||||
break: "minecraft:block.crop.break"
|
break: "minecraft:block.crop.break"
|
||||||
@@ -614,7 +614,7 @@ templates#settings#break_level:
|
|||||||
# block settings
|
# block settings
|
||||||
templates#settings#blocks:
|
templates#settings#blocks:
|
||||||
default:settings/middle_click_pick_itself:
|
default:settings/middle_click_pick_itself:
|
||||||
item: "{__NAMESPACE__}:{__ID__}"
|
item: "${__NAMESPACE__}:${__ID__}"
|
||||||
default:settings/solid_1x1x1:
|
default:settings/solid_1x1x1:
|
||||||
is-suffocating: true
|
is-suffocating: true
|
||||||
replaceable: false
|
replaceable: false
|
||||||
@@ -696,7 +696,7 @@ templates#settings#blocks:
|
|||||||
default:settings/ore:
|
default:settings/ore:
|
||||||
template:
|
template:
|
||||||
- "default:sound/stone"
|
- "default:sound/stone"
|
||||||
- "default:pickaxe_power/level_{break_power}"
|
- "default:pickaxe_power/level_${break_power}"
|
||||||
overrides:
|
overrides:
|
||||||
hardness: 3.0
|
hardness: 3.0
|
||||||
resistance: 3.0
|
resistance: 3.0
|
||||||
@@ -712,7 +712,7 @@ templates#settings#blocks:
|
|||||||
default:settings/deepslate_ore:
|
default:settings/deepslate_ore:
|
||||||
template:
|
template:
|
||||||
- "default:sound/deepslate"
|
- "default:sound/deepslate"
|
||||||
- "default:pickaxe_power/level_{break_power}"
|
- "default:pickaxe_power/level_${break_power}"
|
||||||
overrides:
|
overrides:
|
||||||
hardness: 4.5
|
hardness: 4.5
|
||||||
resistance: 3.0
|
resistance: 3.0
|
||||||
@@ -735,45 +735,45 @@ templates#block_states:
|
|||||||
default: y
|
default: y
|
||||||
appearances:
|
appearances:
|
||||||
axisY:
|
axisY:
|
||||||
state: "{base_block}:{vanilla_id}"
|
state: "${base_block}:${vanilla_id}"
|
||||||
model:
|
model:
|
||||||
path: "{model_vertical_path}"
|
path: "${model_vertical_path}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:block/cube_column"
|
parent: "minecraft:block/cube_column"
|
||||||
textures:
|
textures:
|
||||||
"end": "{texture_top_path}"
|
"end": "${texture_top_path}"
|
||||||
"side": "{texture_side_path}"
|
"side": "${texture_side_path}"
|
||||||
axisX:
|
axisX:
|
||||||
state: "{base_block}:{vanilla_id}"
|
state: "${base_block}:${vanilla_id}"
|
||||||
model:
|
model:
|
||||||
x: 90
|
x: 90
|
||||||
y: 90
|
y: 90
|
||||||
path: "{model_horizontal_path}"
|
path: "${model_horizontal_path}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:block/cube_column_horizontal"
|
parent: "minecraft:block/cube_column_horizontal"
|
||||||
textures:
|
textures:
|
||||||
"end": "{texture_top_path}"
|
"end": "${texture_top_path}"
|
||||||
"side": "{texture_side_path}"
|
"side": "${texture_side_path}"
|
||||||
axisZ:
|
axisZ:
|
||||||
state: "{base_block}:{vanilla_id}"
|
state: "${base_block}:${vanilla_id}"
|
||||||
model:
|
model:
|
||||||
x: 90
|
x: 90
|
||||||
path: "{model_horizontal_path}"
|
path: "${model_horizontal_path}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:block/cube_column_horizontal"
|
parent: "minecraft:block/cube_column_horizontal"
|
||||||
textures:
|
textures:
|
||||||
"end": "{texture_top_path}"
|
"end": "${texture_top_path}"
|
||||||
"side": "{texture_side_path}"
|
"side": "${texture_side_path}"
|
||||||
variants:
|
variants:
|
||||||
axis=x:
|
axis=x:
|
||||||
appearance: axisX
|
appearance: axisX
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
axis=y:
|
axis=y:
|
||||||
appearance: axisY
|
appearance: axisY
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
axis=z:
|
axis=z:
|
||||||
appearance: axisZ
|
appearance: axisZ
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
default:block_state/leaves:
|
default:block_state/leaves:
|
||||||
properties:
|
properties:
|
||||||
waterlogged:
|
waterlogged:
|
||||||
@@ -788,107 +788,107 @@ templates#block_states:
|
|||||||
range: 1~7
|
range: 1~7
|
||||||
appearances:
|
appearances:
|
||||||
default:
|
default:
|
||||||
state: "{default_state}"
|
state: "${default_state}"
|
||||||
model:
|
model:
|
||||||
path: "{model_path}"
|
path: "${model_path}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:block/leaves"
|
parent: "minecraft:block/leaves"
|
||||||
textures:
|
textures:
|
||||||
"all": "{texture_path}"
|
"all": "${texture_path}"
|
||||||
waterlogged:
|
waterlogged:
|
||||||
state: "{waterlogged_state}"
|
state: "${waterlogged_state}"
|
||||||
model:
|
model:
|
||||||
path: "{model_path}"
|
path: "${model_path}"
|
||||||
variants:
|
variants:
|
||||||
distance=1,persistent=false,waterlogged=false:
|
distance=1,persistent=false,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=2,persistent=false,waterlogged=false:
|
distance=2,persistent=false,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=3,persistent=false,waterlogged=false:
|
distance=3,persistent=false,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=4,persistent=false,waterlogged=false:
|
distance=4,persistent=false,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=5,persistent=false,waterlogged=false:
|
distance=5,persistent=false,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=6,persistent=false,waterlogged=false:
|
distance=6,persistent=false,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=7,persistent=false,waterlogged=false:
|
distance=7,persistent=false,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
is-randomly-ticking: true
|
is-randomly-ticking: true
|
||||||
distance=1,persistent=true,waterlogged=false:
|
distance=1,persistent=true,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=2,persistent=true,waterlogged=false:
|
distance=2,persistent=true,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=3,persistent=true,waterlogged=false:
|
distance=3,persistent=true,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=4,persistent=true,waterlogged=false:
|
distance=4,persistent=true,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=5,persistent=true,waterlogged=false:
|
distance=5,persistent=true,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=6,persistent=true,waterlogged=false:
|
distance=6,persistent=true,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=7,persistent=true,waterlogged=false:
|
distance=7,persistent=true,waterlogged=false:
|
||||||
appearance: "default"
|
appearance: "default"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
distance=1,persistent=false,waterlogged=true:
|
distance=1,persistent=false,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=2,persistent=false,waterlogged=true:
|
distance=2,persistent=false,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=3,persistent=false,waterlogged=true:
|
distance=3,persistent=false,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=4,persistent=false,waterlogged=true:
|
distance=4,persistent=false,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=5,persistent=false,waterlogged=true:
|
distance=5,persistent=false,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=6,persistent=false,waterlogged=true:
|
distance=6,persistent=false,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=7,persistent=false,waterlogged=true:
|
distance=7,persistent=false,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
@@ -896,49 +896,49 @@ templates#block_states:
|
|||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=1,persistent=true,waterlogged=true:
|
distance=1,persistent=true,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=2,persistent=true,waterlogged=true:
|
distance=2,persistent=true,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=3,persistent=true,waterlogged=true:
|
distance=3,persistent=true,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=4,persistent=true,waterlogged=true:
|
distance=4,persistent=true,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=5,persistent=true,waterlogged=true:
|
distance=5,persistent=true,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=6,persistent=true,waterlogged=true:
|
distance=6,persistent=true,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
fluid-state: water
|
fluid-state: water
|
||||||
distance=7,persistent=true,waterlogged=true:
|
distance=7,persistent=true,waterlogged=true:
|
||||||
appearance: "waterlogged"
|
appearance: "waterlogged"
|
||||||
id: "{internal_id}"
|
id: "${internal_id}"
|
||||||
settings:
|
settings:
|
||||||
resistance: 1200.0
|
resistance: 1200.0
|
||||||
burnable: false
|
burnable: false
|
||||||
@@ -951,9 +951,9 @@ templates#recipes:
|
|||||||
category: building
|
category: building
|
||||||
group: planks
|
group: planks
|
||||||
ingredients:
|
ingredients:
|
||||||
A: "#default:{wood_type}_logs"
|
A: "#default:${wood_type}_logs"
|
||||||
result:
|
result:
|
||||||
id: "default:{wood_type}_planks"
|
id: "default:${wood_type}_planks"
|
||||||
count: 4
|
count: 4
|
||||||
default:recipe/log_2_wood:
|
default:recipe/log_2_wood:
|
||||||
type: shaped
|
type: shaped
|
||||||
@@ -963,29 +963,29 @@ templates#recipes:
|
|||||||
- "AA"
|
- "AA"
|
||||||
- "AA"
|
- "AA"
|
||||||
ingredients:
|
ingredients:
|
||||||
A: "default:{wood_type}_log"
|
A: "default:${wood_type}_log"
|
||||||
result:
|
result:
|
||||||
id: "default:{wood_type}_wood"
|
id: "default:${wood_type}_wood"
|
||||||
count: 3
|
count: 3
|
||||||
default:recipe/smelting_ore:
|
default:recipe/smelting_ore:
|
||||||
type: smelting
|
type: smelting
|
||||||
experience: "{exp}"
|
experience: "${exp}"
|
||||||
category: misc
|
category: misc
|
||||||
group: topaz
|
group: topaz
|
||||||
time: 200
|
time: 200
|
||||||
ingredient: "{ingredient}"
|
ingredient: "${ingredient}"
|
||||||
result:
|
result:
|
||||||
id: "{result}"
|
id: "${result}"
|
||||||
count: 1
|
count: 1
|
||||||
default:recipe/blasting_ore:
|
default:recipe/blasting_ore:
|
||||||
type: blasting
|
type: blasting
|
||||||
experience: "{exp}"
|
experience: "${exp}"
|
||||||
category: misc
|
category: misc
|
||||||
group: topaz
|
group: topaz
|
||||||
time: 100
|
time: 100
|
||||||
ingredient: "{ingredient}"
|
ingredient: "${ingredient}"
|
||||||
result:
|
result:
|
||||||
id: "{result}"
|
id: "${result}"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
||||||
# loot tables
|
# loot tables
|
||||||
@@ -1001,7 +1001,7 @@ templates#loot_tables:
|
|||||||
- type: survives_explosion
|
- type: survives_explosion
|
||||||
entries:
|
entries:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{__NAMESPACE__}:{__ID__}"
|
item: "${__NAMESPACE__}:${__ID__}"
|
||||||
|
|
||||||
# drop one item
|
# drop one item
|
||||||
|
|
||||||
@@ -1015,7 +1015,7 @@ templates#loot_tables:
|
|||||||
- type: survives_explosion
|
- type: survives_explosion
|
||||||
entries:
|
entries:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{item}"
|
item: "${item}"
|
||||||
|
|
||||||
# drop the original furniture item or a fallback item
|
# drop the original furniture item or a fallback item
|
||||||
|
|
||||||
@@ -1027,7 +1027,7 @@ templates#loot_tables:
|
|||||||
- rolls: 1
|
- rolls: 1
|
||||||
entries:
|
entries:
|
||||||
- type: furniture_item
|
- type: furniture_item
|
||||||
item: "{item}"
|
item: "${item}"
|
||||||
|
|
||||||
# drop with silk touch
|
# drop with silk touch
|
||||||
|
|
||||||
@@ -1042,7 +1042,7 @@ templates#loot_tables:
|
|||||||
predicate: minecraft:silk_touch>=1
|
predicate: minecraft:silk_touch>=1
|
||||||
entries:
|
entries:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{item}"
|
item: "${item}"
|
||||||
|
|
||||||
# crop drops
|
# crop drops
|
||||||
|
|
||||||
@@ -1058,21 +1058,21 @@ templates#loot_tables:
|
|||||||
- type: alternatives
|
- type: alternatives
|
||||||
children:
|
children:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{crop_item}"
|
item: "${crop_item}"
|
||||||
conditions:
|
conditions:
|
||||||
- type: match_block_property
|
- type: match_block_property
|
||||||
properties:
|
properties:
|
||||||
age: "{ripe_age}"
|
age: "${ripe_age}"
|
||||||
- type: item
|
- type: item
|
||||||
item: "{crop_seed}"
|
item: "${crop_seed}"
|
||||||
- rolls: 1
|
- rolls: 1
|
||||||
conditions:
|
conditions:
|
||||||
- type: match_block_property
|
- type: match_block_property
|
||||||
properties:
|
properties:
|
||||||
age: "{ripe_age}"
|
age: "${ripe_age}"
|
||||||
entries:
|
entries:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{crop_seed}"
|
item: "${crop_seed}"
|
||||||
functions:
|
functions:
|
||||||
- type: apply_bonus
|
- type: apply_bonus
|
||||||
enchantment: minecraft:fortune
|
enchantment: minecraft:fortune
|
||||||
@@ -1090,15 +1090,15 @@ templates#loot_tables:
|
|||||||
- rolls: 1
|
- rolls: 1
|
||||||
entries:
|
entries:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{crop_item}"
|
item: "${crop_item}"
|
||||||
- rolls: 1
|
- rolls: 1
|
||||||
conditions:
|
conditions:
|
||||||
- type: match_block_property
|
- type: match_block_property
|
||||||
properties:
|
properties:
|
||||||
age: "{ripe_age}"
|
age: "${ripe_age}"
|
||||||
entries:
|
entries:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{crop_item}"
|
item: "${crop_item}"
|
||||||
functions:
|
functions:
|
||||||
- type: apply_bonus
|
- type: apply_bonus
|
||||||
enchantment: minecraft:fortune
|
enchantment: minecraft:fortune
|
||||||
@@ -1122,12 +1122,12 @@ templates#loot_tables:
|
|||||||
- type: alternatives
|
- type: alternatives
|
||||||
children:
|
children:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{ore_block}"
|
item: "${ore_block}"
|
||||||
conditions:
|
conditions:
|
||||||
- type: enchantment
|
- type: enchantment
|
||||||
predicate: minecraft:silk_touch>=1
|
predicate: minecraft:silk_touch>=1
|
||||||
- type: item
|
- type: item
|
||||||
item: "{ore_drop}"
|
item: "${ore_drop}"
|
||||||
functions:
|
functions:
|
||||||
- type: apply_bonus
|
- type: apply_bonus
|
||||||
enchantment: minecraft:fortune
|
enchantment: minecraft:fortune
|
||||||
@@ -1137,8 +1137,8 @@ templates#loot_tables:
|
|||||||
- type: drop_exp
|
- type: drop_exp
|
||||||
count:
|
count:
|
||||||
type: uniform
|
type: uniform
|
||||||
min: "{min_exp}"
|
min: "${min_exp:-2}"
|
||||||
max: "{max_exp}"
|
max: "${max_exp:-4}"
|
||||||
|
|
||||||
# template: default:loot_table/ore_no_exp
|
# template: default:loot_table/ore_no_exp
|
||||||
# arguments:
|
# arguments:
|
||||||
@@ -1151,12 +1151,12 @@ templates#loot_tables:
|
|||||||
- type: alternatives
|
- type: alternatives
|
||||||
children:
|
children:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{ore_block}"
|
item: "${ore_block}"
|
||||||
conditions:
|
conditions:
|
||||||
- type: enchantment
|
- type: enchantment
|
||||||
predicate: minecraft:silk_touch>=1
|
predicate: minecraft:silk_touch>=1
|
||||||
- type: item
|
- type: item
|
||||||
item: "{ore_drop}"
|
item: "${ore_drop}"
|
||||||
functions:
|
functions:
|
||||||
- type: apply_bonus
|
- type: apply_bonus
|
||||||
enchantment: minecraft:fortune
|
enchantment: minecraft:fortune
|
||||||
@@ -1177,7 +1177,7 @@ templates#loot_tables:
|
|||||||
- type: alternatives
|
- type: alternatives
|
||||||
children:
|
children:
|
||||||
- type: item
|
- type: item
|
||||||
item: "{leaves}"
|
item: "${leaves}"
|
||||||
conditions:
|
conditions:
|
||||||
- type: any_of
|
- type: any_of
|
||||||
terms:
|
terms:
|
||||||
@@ -1186,7 +1186,7 @@ templates#loot_tables:
|
|||||||
- type: enchantment
|
- type: enchantment
|
||||||
predicate: minecraft:silk_touch>=1
|
predicate: minecraft:silk_touch>=1
|
||||||
- type: item
|
- type: item
|
||||||
item: "{sapling}"
|
item: "${sapling}"
|
||||||
conditions:
|
conditions:
|
||||||
- type: survives_explosion
|
- type: survives_explosion
|
||||||
- type: table_bonus
|
- type: table_bonus
|
||||||
|
|||||||
@@ -69,21 +69,21 @@ images:
|
|||||||
templates:
|
templates:
|
||||||
internal:icon/2d:
|
internal:icon/2d:
|
||||||
material: arrow
|
material: arrow
|
||||||
custom-model-data: "{model_data}"
|
custom-model-data: "${model_data}"
|
||||||
data:
|
data:
|
||||||
item-name: "{name}"
|
item-name: "${name}"
|
||||||
lore: "{lore}"
|
lore: "${lore}"
|
||||||
model:
|
model:
|
||||||
template: "internal:model/simplified_generated"
|
template: "internal:model/simplified_generated"
|
||||||
arguments:
|
arguments:
|
||||||
path: "minecraft:item/custom/gui/{texture}"
|
path: "minecraft:item/custom/gui/${texture}"
|
||||||
internal:model/simplified_generated:
|
internal:model/simplified_generated:
|
||||||
type: "minecraft:model"
|
type: "minecraft:model"
|
||||||
path: "{path}"
|
path: "${path}"
|
||||||
generation:
|
generation:
|
||||||
parent: "minecraft:item/generated"
|
parent: "minecraft:item/generated"
|
||||||
textures:
|
textures:
|
||||||
"layer0": "{path}"
|
"layer0": "${path}"
|
||||||
|
|
||||||
items:
|
items:
|
||||||
internal:next_page_0:
|
internal:next_page_0:
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ command.upload.on_progress: "<white>Started uploading progress. Check the consol
|
|||||||
command.send_resource_pack.success.single: "<white>Sent resource pack to <arg:0>.</white>"
|
command.send_resource_pack.success.single: "<white>Sent resource pack to <arg:0>.</white>"
|
||||||
command.send_resource_pack.success.multiple: "<white>Send resource packs to <arg:0> players.</white>"
|
command.send_resource_pack.success.multiple: "<white>Send resource packs to <arg:0> players.</white>"
|
||||||
warning.config.pack.duplicated_files: "</red>Duplicated files Found. Please resolve them through config.yml 'resource-pack.duplicated-files-handler' section.</red>"
|
warning.config.pack.duplicated_files: "</red>Duplicated files Found. Please resolve them through config.yml 'resource-pack.duplicated-files-handler' section.</red>"
|
||||||
|
warning.config.yaml.duplicated_key: "<red>Issue found in file <arg:0> - Found duplicated key '<arg:1>' at line <arg:2>, this might cause unexpected results.</red>"
|
||||||
warning.config.type.int: "<yellow>Issue found in file <arg:0> - Failed to load '<arg:1>': Cannot cast '<arg:2>' to integer type for option '<arg:3>'.</yellow>"
|
warning.config.type.int: "<yellow>Issue found in file <arg:0> - Failed to load '<arg:1>': Cannot cast '<arg:2>' to integer type for option '<arg:3>'.</yellow>"
|
||||||
warning.config.type.float: "<yellow>Issue found in file <arg:0> - Failed to load '<arg:1>': Cannot cast '<arg:2>' to float type for option '<arg:3>'.</yellow>"
|
warning.config.type.float: "<yellow>Issue found in file <arg:0> - Failed to load '<arg:1>': Cannot cast '<arg:2>' to float type for option '<arg:3>'.</yellow>"
|
||||||
warning.config.type.double: "<yellow>Issue found in file <arg:0> - Failed to load '<arg:1>': Cannot cast '<arg:2>' to double type for option '<arg:3>'.</yellow>"
|
warning.config.type.double: "<yellow>Issue found in file <arg:0> - Failed to load '<arg:1>': Cannot cast '<arg:2>' to double type for option '<arg:3>'.</yellow>"
|
||||||
@@ -113,7 +114,6 @@ warning.config.image.missing_char: "<yellow>Issue found in file <arg:0> - The im
|
|||||||
warning.config.image.codepoint_conflict: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is using a character '<arg:3>(<arg:4>)' in font <arg:2> that has been used by another image '<arg:5>'.</yellow>"
|
warning.config.image.codepoint_conflict: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is using a character '<arg:3>(<arg:4>)' in font <arg:2> that has been used by another image '<arg:5>'.</yellow>"
|
||||||
warning.config.image.invalid_codepoint_grid: "<yellow>Issue found in file <arg:0> - Image '<arg:1>' has an invalid 'chars' codepoint grid.</yellow>"
|
warning.config.image.invalid_codepoint_grid: "<yellow>Issue found in file <arg:0> - Image '<arg:1>' has an invalid 'chars' codepoint grid.</yellow>"
|
||||||
warning.config.image.invalid_char: "<yellow>Issue found in file <arg:0> - Image '<arg:1>' has a char parameter containing combining characters, which may result in image splitting.</yellow>"
|
warning.config.image.invalid_char: "<yellow>Issue found in file <arg:0> - Image '<arg:1>' has a char parameter containing combining characters, which may result in image splitting.</yellow>"
|
||||||
warning.config.image.file_not_found: "<yellow>Issue found in file <arg:0> - PNG file '<arg:2>' not found for image '<arg:1>'.</yellow>"
|
|
||||||
warning.config.image.invalid_hex_value: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is using a unicode character '<arg:2>' that is not a valid hexadecimal (radix 16) value.</yellow>"
|
warning.config.image.invalid_hex_value: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is using a unicode character '<arg:2>' that is not a valid hexadecimal (radix 16) value.</yellow>"
|
||||||
warning.config.recipe.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated recipe '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
warning.config.recipe.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated recipe '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
||||||
warning.config.recipe.missing_type: "<yellow>Issue found in file <arg:0> - The recipe '<arg:1>' is missing the required 'type' argument.</yellow>"
|
warning.config.recipe.missing_type: "<yellow>Issue found in file <arg:0> - The recipe '<arg:1>' is missing the required 'type' argument.</yellow>"
|
||||||
@@ -133,8 +133,10 @@ warning.config.recipe.smithing_transform.post_processor.keep_component.missing_c
|
|||||||
warning.config.recipe.smithing_transform.post_processor.keep_component.missing_tags: "<yellow>Issue found in file <arg:0> - The smithing transform recipe '<arg:1>' is missing the required argument 'tags' for post-processors 'keep_tags'.</yellow>"
|
warning.config.recipe.smithing_transform.post_processor.keep_component.missing_tags: "<yellow>Issue found in file <arg:0> - The smithing transform recipe '<arg:1>' is missing the required argument 'tags' for post-processors 'keep_tags'.</yellow>"
|
||||||
warning.config.i18n.unknown_locale: "<yellow>Issue found in file <arg:0> - Unknown locale '<arg:1>'.</yellow>"
|
warning.config.i18n.unknown_locale: "<yellow>Issue found in file <arg:0> - Unknown locale '<arg:1>'.</yellow>"
|
||||||
warning.config.template.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated template '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
warning.config.template.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated template '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
||||||
|
warning.config.template.invalid: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid template '<arg:2>'.</yellow>"
|
||||||
warning.config.template.argument.self_increase_int.invalid_range: "<yellow>Issue found in file <arg:0> - The template '<arg:1>' is using a 'from' '<arg:2>' larger than 'to' '<arg:3>' in 'self_increase_int' argument.</yellow>"
|
warning.config.template.argument.self_increase_int.invalid_range: "<yellow>Issue found in file <arg:0> - The template '<arg:1>' is using a 'from' '<arg:2>' larger than 'to' '<arg:3>' in 'self_increase_int' argument.</yellow>"
|
||||||
warning.config.template.argument.list.invalid_type: "<yellow>Issue found in file <arg:0> - The template '<arg:1>' is using a 'list' argument which expects a 'List' as argument while the input argument is a(n) '<arg:2>'.</yellow>"
|
warning.config.template.argument.list.invalid_type: "<yellow>Issue found in file <arg:0> - The template '<arg:1>' is using a 'list' argument which expects a 'List' as argument while the input argument is a(n) '<arg:2>'.</yellow>"
|
||||||
|
warning.config.template.argument.default_value.invalid_syntax: "<yellow>Issue found in file <arg:0> - The template '<arg:1>' is using an invalid default value '<arg:2>' for argument '<arg:3>'.</yellow>"
|
||||||
warning.config.vanilla_loot.missing_type: "<yellow>Issue found in file <arg:0> - The vanilla loot '<arg:1>' is missing the required 'type' argument.</yellow>"
|
warning.config.vanilla_loot.missing_type: "<yellow>Issue found in file <arg:0> - The vanilla loot '<arg:1>' is missing the required 'type' argument.</yellow>"
|
||||||
warning.config.vanilla_loot.invalid_type: "<yellow>Issue found in file <arg:0> - The vanilla loot '<arg:1>' is using an invalid type '<arg:2>'. Allowed types: [<arg:3>].</yellow>"
|
warning.config.vanilla_loot.invalid_type: "<yellow>Issue found in file <arg:0> - The vanilla loot '<arg:1>' is using an invalid type '<arg:2>'. Allowed types: [<arg:3>].</yellow>"
|
||||||
warning.config.vanilla_loot.block.invalid_target: "<yellow>Issue found in file <arg:0> - Invalid block target '<arg:2>' in vanilla loot '<arg:1>'.</yellow>"
|
warning.config.vanilla_loot.block.invalid_target: "<yellow>Issue found in file <arg:0> - Invalid block target '<arg:2>' in vanilla loot '<arg:1>'.</yellow>"
|
||||||
@@ -151,11 +153,13 @@ warning.config.furniture.hitbox.invalid_type: "<yellow>Issue found in file <arg:
|
|||||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using a custom hitbox with invalid entity type '<arg:2>'.</yellow>"
|
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using a custom hitbox with invalid entity type '<arg:2>'.</yellow>"
|
||||||
warning.config.item.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated item '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
warning.config.item.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated item '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
||||||
warning.config.item.settings.unknown: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an unknown setting type '<arg:2>'.</yellow>"
|
warning.config.item.settings.unknown: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an unknown setting type '<arg:2>'.</yellow>"
|
||||||
|
warning.config.item.settings.invulnerable.invalid_damage_source: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an unknown damage source '<arg:2>'. Allowed sources: [<arg:3>].</yellow>"
|
||||||
warning.config.item.missing_material: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'material' argument.</yellow>"
|
warning.config.item.missing_material: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'material' argument.</yellow>"
|
||||||
warning.config.item.invalid_material: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an invalid material type '<arg:2>'.</yellow>"
|
warning.config.item.invalid_material: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an invalid material type '<arg:2>'.</yellow>"
|
||||||
warning.config.item.invalid_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a negative custom model data '<arg:2>' which is invalid.</yellow>"
|
warning.config.item.invalid_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a negative custom model data '<arg:2>' which is invalid.</yellow>"
|
||||||
warning.config.item.bad_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that is too large. It's recommended to use a value lower than 16,777,216.</yellow>"
|
warning.config.item.bad_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that is too large. It's recommended to use a value lower than 16,777,216.</yellow>"
|
||||||
warning.config.item.custom_model_data_conflict: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that has been occupied by item '<arg:3>'.</yellow>"
|
warning.config.item.custom_model_data_conflict: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that has been occupied by item '<arg:3>'.</yellow>"
|
||||||
|
warning.config.item.invalid_component: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a non-existing component type '<arg:2>'.</yellow>"
|
||||||
warning.config.item.missing_model_id: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'custom-model-data' or 'item-model' argument.</yellow>"
|
warning.config.item.missing_model_id: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'custom-model-data' or 'item-model' argument.</yellow>"
|
||||||
warning.config.item.missing_model: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'model' section for 1.21.4+ resource pack support.</yellow>"
|
warning.config.item.missing_model: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'model' section for 1.21.4+ resource pack support.</yellow>"
|
||||||
warning.config.item.behavior.missing_type: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'type' argument for its item behavior.</yellow>"
|
warning.config.item.behavior.missing_type: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'type' argument for its item behavior.</yellow>"
|
||||||
@@ -350,3 +354,8 @@ warning.config.selector.invalid_target: "<yellow>Issue found in file <arg:0> - T
|
|||||||
warning.config.resource_pack.item_model.conflict.vanilla: "<yellow>Failed to generate item model for '<arg:0>' because this item model has been occupied by a vanilla item.</yellow>"
|
warning.config.resource_pack.item_model.conflict.vanilla: "<yellow>Failed to generate item model for '<arg:0>' because this item model has been occupied by a vanilla item.</yellow>"
|
||||||
warning.config.resource_pack.item_model.already_exist: "<yellow>Failed to generate item model for '<arg:0>' because the file '<arg:1>' already exists.</yellow>"
|
warning.config.resource_pack.item_model.already_exist: "<yellow>Failed to generate item model for '<arg:0>' because the file '<arg:1>' already exists.</yellow>"
|
||||||
warning.config.resource_pack.model.generation.already_exist: "<yellow>Failed to generate model because the model file '<arg:0>' already exists.</yellow>"
|
warning.config.resource_pack.model.generation.already_exist: "<yellow>Failed to generate model because the model file '<arg:0>' already exists.</yellow>"
|
||||||
|
warning.config.resource_pack.generation.missing_font_texture: "<yellow>Font '<arg:0>' is missing required texture: '<arg:1>'</yellow>"
|
||||||
|
warning.config.resource_pack.generation.missing_model_texture: "<yellow>Model '<arg:0>' is missing texture '<arg:1>'</yellow>"
|
||||||
|
warning.config.resource_pack.generation.missing_item_model: "<yellow>Item '<arg:0>' is missing model file: '<arg:1>'</yellow>"
|
||||||
|
warning.config.resource_pack.generation.missing_block_model: "<yellow>Block '<arg:0>' is missing model file: '<arg:1>'</yellow>"
|
||||||
|
warning.config.resource_pack.generation.missing_parent_model: "<yellow>Model '<arg:0>' cannot find parent model: '<arg:1>'</yellow>"
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user