fix: 1.21.9+ client crash and add copper golem support
- Fix skinLayersIndex for 1.21.9+ (index 16 instead of 17) - Fix shoulderIndex offset for 1.21.9+ - Refactor Viewable to use shared ExecutorService - Add CopperGolemState and WeatheringCopperState enums - Register copper_golem entity type for 1.21.9+ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b6f878bdc0
commit
d1444642ae
6 changed files with 52 additions and 36 deletions
|
|
@ -0,0 +1,9 @@
|
||||||
|
package lol.pyr.znpcsplus.util;
|
||||||
|
|
||||||
|
public enum CopperGolemState {
|
||||||
|
IDLE,
|
||||||
|
GETTING_ITEM,
|
||||||
|
GETTING_NO_ITEM,
|
||||||
|
DROPPING_ITEM,
|
||||||
|
DROPPING_NO_ITEM
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package lol.pyr.znpcsplus.util;
|
||||||
|
|
||||||
|
public enum WeatheringCopperState {
|
||||||
|
UNAFFECTED,
|
||||||
|
EXPOSED,
|
||||||
|
WEATHERED,
|
||||||
|
OXIDIZED
|
||||||
|
}
|
||||||
|
|
@ -66,10 +66,7 @@ import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ZNpcsPlus {
|
public class ZNpcsPlus {
|
||||||
private final LegacyComponentSerializer textSerializer = LegacyComponentSerializer.builder()
|
private final LegacyComponentSerializer textSerializer = LegacyComponentSerializer.builder()
|
||||||
|
|
@ -98,6 +95,7 @@ public class ZNpcsPlus {
|
||||||
|
|
||||||
NpcPropertyRegistryProvider.register(bootstrap, propertyRegistry);
|
NpcPropertyRegistryProvider.register(bootstrap, propertyRegistry);
|
||||||
shutdownTasks.add(NpcPropertyRegistryProvider::unregister);
|
shutdownTasks.add(NpcPropertyRegistryProvider::unregister);
|
||||||
|
shutdownTasks.add(Viewable::shutdownExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void log(String str) {
|
private void log(String str) {
|
||||||
|
|
@ -215,6 +213,7 @@ public class ZNpcsPlus {
|
||||||
|
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
NpcApiProvider.unregister();
|
NpcApiProvider.unregister();
|
||||||
|
Collections.reverse(shutdownTasks);
|
||||||
for (Runnable runnable : shutdownTasks) try {
|
for (Runnable runnable : shutdownTasks) try {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
|
|
@ -297,6 +296,8 @@ public class ZNpcsPlus {
|
||||||
registerEnumParser(manager, WoldVariant.class, incorrectUsageMessage);
|
registerEnumParser(manager, WoldVariant.class, incorrectUsageMessage);
|
||||||
registerEnumParser(manager, NpcStorageType.class, incorrectUsageMessage);
|
registerEnumParser(manager, NpcStorageType.class, incorrectUsageMessage);
|
||||||
registerEnumParser(manager, SkeletonType.class, incorrectUsageMessage);
|
registerEnumParser(manager, SkeletonType.class, incorrectUsageMessage);
|
||||||
|
registerEnumParser(manager, CopperGolemState.class, incorrectUsageMessage);
|
||||||
|
registerEnumParser(manager, WeatheringCopperState.class, incorrectUsageMessage);
|
||||||
|
|
||||||
manager.registerCommand("npc", new MultiCommand(bootstrap.loadHelpMessage("root"))
|
manager.registerCommand("npc", new MultiCommand(bootstrap.loadHelpMessage("root"))
|
||||||
.addSubcommand("center", new CenterCommand(npcRegistry))
|
.addSubcommand("center", new CenterCommand(npcRegistry))
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,8 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
||||||
registerEnumSerializer(ArmadilloState.class);
|
registerEnumSerializer(ArmadilloState.class);
|
||||||
registerEnumSerializer(WoldVariant.class);
|
registerEnumSerializer(WoldVariant.class);
|
||||||
registerEnumSerializer(SkeletonType.class);
|
registerEnumSerializer(SkeletonType.class);
|
||||||
|
registerEnumSerializer(CopperGolemState.class);
|
||||||
|
registerEnumSerializer(WeatheringCopperState.class);
|
||||||
|
|
||||||
registerPrimitiveSerializers(Integer.class, Boolean.class, Double.class, Float.class, Long.class, Short.class, Byte.class, String.class);
|
registerPrimitiveSerializers(Integer.class, Boolean.class, Double.class, Float.class, Long.class, Short.class, Byte.class, String.class);
|
||||||
|
|
||||||
|
|
@ -201,7 +203,8 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
||||||
// Player
|
// Player
|
||||||
register(new DummyProperty<>("skin", SkinDescriptor.class, false));
|
register(new DummyProperty<>("skin", SkinDescriptor.class, false));
|
||||||
final int skinLayersIndex;
|
final int skinLayersIndex;
|
||||||
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) skinLayersIndex = 17;
|
if (ver.isNewerThanOrEquals(ServerVersion.V_1_21_9)) skinLayersIndex = 16;
|
||||||
|
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) skinLayersIndex = 17;
|
||||||
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_16)) skinLayersIndex = 16;
|
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_16)) skinLayersIndex = 16;
|
||||||
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) skinLayersIndex = 15;
|
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) skinLayersIndex = 15;
|
||||||
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) skinLayersIndex = 13;
|
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) skinLayersIndex = 13;
|
||||||
|
|
@ -561,6 +564,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
||||||
return compound;
|
return compound;
|
||||||
};
|
};
|
||||||
int shoulderIndex = skinLayersIndex+2;
|
int shoulderIndex = skinLayersIndex+2;
|
||||||
|
if (ver.isNewerThanOrEquals(ServerVersion.V_1_21_9)) shoulderIndex += 1;
|
||||||
register(new NBTProperty<>("shoulder_entity_left", ParrotVariant.class, shoulderIndex++, parrotVariantDecoder, true));
|
register(new NBTProperty<>("shoulder_entity_left", ParrotVariant.class, shoulderIndex++, parrotVariantDecoder, true));
|
||||||
register(new NBTProperty<>("shoulder_entity_right", ParrotVariant.class, shoulderIndex, parrotVariantDecoder, true));
|
register(new NBTProperty<>("shoulder_entity_right", ParrotVariant.class, shoulderIndex, parrotVariantDecoder, true));
|
||||||
|
|
||||||
|
|
@ -734,6 +738,12 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
||||||
|
|
||||||
// Creaking
|
// Creaking
|
||||||
register(new BooleanProperty("creaking_crumbling", 18, false, legacyBooleans));
|
register(new BooleanProperty("creaking_crumbling", 18, false, legacyBooleans));
|
||||||
|
|
||||||
|
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_21_9)) return;
|
||||||
|
|
||||||
|
// Copper Golem
|
||||||
|
register(new EncodedIntegerProperty<>("weathering_copper_state", WeatheringCopperState.UNAFFECTED, 16, Enum::ordinal));
|
||||||
|
register(new EncodedIntegerProperty<>("copper_golem_state", CopperGolemState.IDLE, 17, Enum::ordinal));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerSerializer(PropertySerializer<?> serializer) {
|
private void registerSerializer(PropertySerializer<?> serializer) {
|
||||||
|
|
|
||||||
|
|
@ -402,6 +402,12 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
|
||||||
register(builder(p, "creaking", EntityTypes.CREAKING)
|
register(builder(p, "creaking", EntityTypes.CREAKING)
|
||||||
.setHologramOffset(0.725)
|
.setHologramOffset(0.725)
|
||||||
.addProperties("creaking_active"));
|
.addProperties("creaking_active"));
|
||||||
|
|
||||||
|
if (!version.isNewerThanOrEquals(ServerVersion.V_1_21_9)) return;
|
||||||
|
|
||||||
|
register(builder(p, "copper_golem", EntityTypes.COPPER_GOLEM)
|
||||||
|
.setHologramOffset(-0.995)
|
||||||
|
.addProperties("weathering_copper_state", "copper_golem_state"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<NpcType> getAll() {
|
public Collection<NpcType> getAll() {
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,7 @@ import org.bukkit.entity.Player;
|
||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class Viewable {
|
public abstract class Viewable {
|
||||||
|
|
@ -22,34 +20,20 @@ public abstract class Viewable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean queueRunning = false;
|
private final static ExecutorService visibilityExecutor = Executors.newSingleThreadExecutor();
|
||||||
private final Queue<Runnable> visibilityTaskQueue = new ConcurrentLinkedQueue<>();
|
|
||||||
|
public static void shutdownExecutor() {
|
||||||
|
visibilityExecutor.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
private final Set<Player> viewers = ConcurrentHashMap.newKeySet();
|
private final Set<Player> viewers = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
public Viewable() {
|
public Viewable() {
|
||||||
all.add(new WeakReference<>(this));
|
all.add(new WeakReference<>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryRunQueue() {
|
|
||||||
if (visibilityTaskQueue.isEmpty() || queueRunning) return;
|
|
||||||
queueRunning = true;
|
|
||||||
FutureUtil.exceptionPrintingRunAsync(() -> {
|
|
||||||
while (!visibilityTaskQueue.isEmpty()) try {
|
|
||||||
visibilityTaskQueue.remove().run();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
queueRunning = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void queueVisibilityTask(Runnable runnable) {
|
|
||||||
visibilityTaskQueue.add(runnable);
|
|
||||||
tryRunQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
queueVisibilityTask(() -> {
|
visibilityExecutor.submit(() -> {
|
||||||
UNSAFE_hideAll();
|
UNSAFE_hideAll();
|
||||||
viewers.clear();
|
viewers.clear();
|
||||||
synchronized (all) {
|
synchronized (all) {
|
||||||
|
|
@ -60,10 +44,9 @@ public abstract class Viewable {
|
||||||
|
|
||||||
public CompletableFuture<Void> respawn() {
|
public CompletableFuture<Void> respawn() {
|
||||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||||
queueVisibilityTask(() -> {
|
visibilityExecutor.submit(() -> {
|
||||||
UNSAFE_hideAll();
|
UNSAFE_hideAll();
|
||||||
UNSAFE_showAll().join();
|
UNSAFE_showAll().thenRun(() -> future.complete(null));
|
||||||
future.complete(null);
|
|
||||||
});
|
});
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
@ -75,20 +58,19 @@ public abstract class Viewable {
|
||||||
|
|
||||||
public CompletableFuture<Void> show(Player player) {
|
public CompletableFuture<Void> show(Player player) {
|
||||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||||
queueVisibilityTask(() -> {
|
visibilityExecutor.submit(() -> {
|
||||||
if (viewers.contains(player)) {
|
if (viewers.contains(player)) {
|
||||||
future.complete(null);
|
future.complete(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
viewers.add(player);
|
viewers.add(player);
|
||||||
UNSAFE_show(player).join();
|
UNSAFE_show(player).thenRun(() -> future.complete(null));
|
||||||
future.complete(null);
|
|
||||||
});
|
});
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hide(Player player) {
|
public void hide(Player player) {
|
||||||
queueVisibilityTask(() -> {
|
visibilityExecutor.submit(() -> {
|
||||||
if (!viewers.contains(player)) return;
|
if (!viewers.contains(player)) return;
|
||||||
viewers.remove(player);
|
viewers.remove(player);
|
||||||
UNSAFE_hide(player);
|
UNSAFE_hide(player);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue