From b45306868f686bef47ae5a6a51b32a1afdae062e Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Tue, 5 Nov 2024 15:12:51 +0800 Subject: [PATCH 1/8] How could this be --- .../morph/events/CommonEventProcessor.java | 4 +++ .../disguise/VanillaDisguiseProvider.java | 26 +++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/java/xyz/nifeather/morph/events/CommonEventProcessor.java b/src/main/java/xyz/nifeather/morph/events/CommonEventProcessor.java index 72106eef..37411515 100644 --- a/src/main/java/xyz/nifeather/morph/events/CommonEventProcessor.java +++ b/src/main/java/xyz/nifeather/morph/events/CommonEventProcessor.java @@ -42,6 +42,7 @@ import xyz.nifeather.morph.misc.playerList.PlayerListHandler; import xyz.nifeather.morph.network.server.MorphClientHandler; import xyz.nifeather.morph.network.server.ServerSetEquipCommand; +import xyz.nifeather.morph.providers.disguise.VanillaDisguiseProvider; import xyz.nifeather.morph.skills.MorphSkillHandler; import xyz.nifeather.morph.utilities.EntityTypeUtils; import xyz.nifeather.morph.utilities.ItemUtils; @@ -410,6 +411,9 @@ public void onPlayerJoin(PlayerJoinEvent e) if (instance == null) continue; instance.removeModifier(AttributeModifyingAbility.modifierKey); + instance.removeModifier(VanillaDisguiseProvider.healthModifierKeyLegacy); + instance.removeModifier(VanillaDisguiseProvider.healthModifierKey); + instance.removeModifier(VanillaDisguiseProvider.healthModifierKeyVanilla); } this.addSchedule(() -> PlayerListHandler.instance().handle(player)); diff --git a/src/main/java/xyz/nifeather/morph/providers/disguise/VanillaDisguiseProvider.java b/src/main/java/xyz/nifeather/morph/providers/disguise/VanillaDisguiseProvider.java index f1e87cb9..1b5b6e07 100644 --- a/src/main/java/xyz/nifeather/morph/providers/disguise/VanillaDisguiseProvider.java +++ b/src/main/java/xyz/nifeather/morph/providers/disguise/VanillaDisguiseProvider.java @@ -88,7 +88,7 @@ public VanillaDisguiseProvider() } private final Bindable armorStandShowArms = new Bindable<>(false); - private final Bindable doHealthScale = new Bindable<>(true); + private final Bindable doHealthScale = new Bindable<>(false); private final Bindable healthCap = new Bindable<>(60); private final Bindable modifyBoundingBoxes = new Bindable<>(false); private final Bindable checkSpaceBoundingBox = new Bindable<>(true); @@ -245,7 +245,11 @@ private void tryAddModifier(DisguiseState state) var entity = NmsUtils.spawnEntity(state.getEntityType(), state.getPlayer().getWorld(), loc); - if (!(entity instanceof LivingEntity living)) return; + if (!(entity instanceof LivingEntity living)) + { + entity.remove(); + return; + } var craftLiving = (net.minecraft.world.entity.LivingEntity) ((CraftLivingEntity)living).getHandleRaw(); var mobMaxHealth = craftLiving.craftAttributes.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue(); @@ -265,12 +269,18 @@ private void tryAddModifier(DisguiseState state) diff = healthCap.get() - playerAttribute.getBaseValue(); //缩放生命值 - double finalDiff = diff; + double diffFinal = diff; this.executeThenScaleHealth(player, playerAttribute, () -> { - var modifier = new AttributeModifier(healthModifierKey, finalDiff, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.ANY); + var modifier = new AttributeModifier(healthModifierKey, diffFinal, AttributeModifier.Operation.ADD_NUMBER); + // In case some data sync plugins not processing correctly, also check for minecraft namespace. + playerAttribute.removeModifier(healthModifierKeyVanilla); playerAttribute.removeModifier(healthModifierKey); + + // Also handle legacy keys + playerAttribute.removeModifier(healthModifierKeyLegacy); + playerAttribute.addModifier(modifier); }); @@ -284,7 +294,13 @@ private void tryAddModifier(DisguiseState state) } @NotNull - public static final NamespacedKey healthModifierKey = Objects.requireNonNull(NamespacedKey.fromString("feathermorph:health_modifier"), "How?!"); + public static final NamespacedKey healthModifierKeyLegacy = Objects.requireNonNull(NamespacedKey.fromString("feathermorph:health_modifier"), "How?!"); + + @NotNull + public static final NamespacedKey healthModifierKey = Objects.requireNonNull(NamespacedKey.fromString("feathermorph:fm_health_modifier"), "How?!"); + + @NotNull + public static final NamespacedKey healthModifierKeyVanilla = Objects.requireNonNull(NamespacedKey.fromString("minecraft:fm_health_modifier"), "How?!"); private void resetPlayerDimensions(Player player) { From 09f618f59e0e1dbeda2dbef0a64de3f78ed81c96 Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Tue, 5 Nov 2024 15:31:33 +0800 Subject: [PATCH 2/8] 1.3.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9f9aa8a6..02b578a6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -project_version=1.3.1 +project_version=1.3.2 # FM Protocols protocols_version=b15c1841 From 60a6a429b3b92d84fe947e49c5c535327ce05a2f Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Tue, 5 Nov 2024 16:41:29 +0800 Subject: [PATCH 3/8] Fix instance network, 1.3.2 for real --- .../multiInstance/MultiInstanceService.java | 11 ++- .../multiInstance/master/InstanceServer.java | 22 ++++-- .../multiInstance/master/MasterInstance.java | 36 ++++++---- .../multiInstance/slave/InstanceClient.java | 71 ++++++++++++++++--- .../multiInstance/slave/SlaveInstance.java | 45 ++++++++---- 5 files changed, 138 insertions(+), 47 deletions(-) diff --git a/src/main/java/xyz/nifeather/morph/network/multiInstance/MultiInstanceService.java b/src/main/java/xyz/nifeather/morph/network/multiInstance/MultiInstanceService.java index 68aadde4..ff0023fd 100644 --- a/src/main/java/xyz/nifeather/morph/network/multiInstance/MultiInstanceService.java +++ b/src/main/java/xyz/nifeather/morph/network/multiInstance/MultiInstanceService.java @@ -137,9 +137,14 @@ public void onReload() private boolean stopAll() { - if (slaveInstance != null) return slaveInstance.stop(); - if (masterInstance != null) return masterInstance.stop(); + boolean success = true; - return true; + if (slaveInstance != null) + success = slaveInstance.stop(); + + if (masterInstance != null) + success = masterInstance.stop() && success; + + return success; } } diff --git a/src/main/java/xyz/nifeather/morph/network/multiInstance/master/InstanceServer.java b/src/main/java/xyz/nifeather/morph/network/multiInstance/master/InstanceServer.java index e2e6e1cf..4557e576 100644 --- a/src/main/java/xyz/nifeather/morph/network/multiInstance/master/InstanceServer.java +++ b/src/main/java/xyz/nifeather/morph/network/multiInstance/master/InstanceServer.java @@ -18,6 +18,16 @@ public final class InstanceServer extends WebSocketServer private final IClientHandler clientHandler; + private void logServerInfo(String message) + { + logger.info("[S@%s] %s".formatted(Integer.toHexString(this.hashCode()), message)); + } + + private void logServerWarn(String message) + { + logger.warn("[S@%s] %s".formatted(Integer.toHexString(this.hashCode()), message)); + } + public InstanceServer(XiaMoJavaPlugin plugin, InetSocketAddress address, IClientHandler iClientHandler) { super(address); @@ -42,7 +52,7 @@ public List getConnectedSockets() @Override public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) { - logger.info("[S] New connection opened: " + webSocket.getRemoteSocketAddress()); + logServerInfo("New connection opened: " + webSocket.getRemoteSocketAddress()); connectedSockets.add(webSocket); } @@ -52,7 +62,7 @@ public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) @Override public void stop(int timeout, String closeMessage) throws InterruptedException { - logger.info("[S] Stopping instance server..."); + logServerInfo("Stopping instance server..."); super.stop(timeout, closeMessage); running = false; @@ -61,7 +71,7 @@ public void stop(int timeout, String closeMessage) throws InterruptedException @Override public void onClose(WebSocket webSocket, int i, String s, boolean b) { - logger.info("[S] Connection closed: " + webSocket.getRemoteSocketAddress()); + logServerInfo("Connection closed: " + webSocket.getRemoteSocketAddress()); connectedSockets.remove(webSocket); clientHandler.onConnectionClose(webSocket); @@ -74,7 +84,7 @@ public record WsRecord(WebSocket socket, String rawMessage) @Override public void onMessage(WebSocket webSocket, String msg) { - //logger.info("%s :: <- :: '%s'".formatted(webSocket.getRemoteSocketAddress(), msg)); + //logServer("%s :: <- :: '%s'".formatted(webSocket.getRemoteSocketAddress(), msg)); clientHandler.onMessage(new WsRecord(webSocket, msg), this); } @@ -85,14 +95,14 @@ public void onError(@Nullable WebSocket webSocket, Exception e) String socketAddress = "".formatted(webSocket); if (webSocket != null) socketAddress = webSocket.getRemoteSocketAddress().toString(); - logger.warn("[S] An error occurred with socket '%s': %s".formatted(socketAddress, e.getMessage())); + logServerWarn("An error occurred with socket '%s': %s".formatted(socketAddress, e.getMessage())); e.printStackTrace(); } @Override public void onStart() { - logger.info("[S] Master websocket server started on " + this.getAddress().toString()); + logServerInfo("Master websocket server started on " + this.getAddress().toString()); clientHandler.onServerStart(this); running = true; diff --git a/src/main/java/xyz/nifeather/morph/network/multiInstance/master/MasterInstance.java b/src/main/java/xyz/nifeather/morph/network/multiInstance/master/MasterInstance.java index e1854be6..9eb7a71d 100644 --- a/src/main/java/xyz/nifeather/morph/network/multiInstance/master/MasterInstance.java +++ b/src/main/java/xyz/nifeather/morph/network/multiInstance/master/MasterInstance.java @@ -42,6 +42,16 @@ public class MasterInstance extends MorphPluginObject implements IInstanceServic @Resolved private MorphConfigManager config; + private void logMasterInfo(String message) + { + logger.info("[Master@%s] %s".formatted(Integer.toHexString(this.hashCode()), message)); + } + + private void logMasterWarn(String message) + { + logger.warn("[Master@%s] %s".formatted(Integer.toHexString(this.hashCode()), message)); + } + /** * @return Success? */ @@ -51,8 +61,8 @@ private boolean stopServer() { if (bindingServer != null) { + bindingServer.stop(1000, "Master instance shutting down"); bindingServer.dispose(); - bindingServer.stop(0, "Master instance shutting down"); } bindingServer = null; @@ -64,7 +74,7 @@ private boolean stopServer() } catch (Throwable t) { - logger.error("[S] Error occurred shutting down socket server: " + t.getMessage()); + logMasterWarn("Error occurred shutting down socket server: " + t.getMessage()); t.printStackTrace(); return false; @@ -99,7 +109,7 @@ private boolean prepareServer() } catch (Throwable t) { - logger.warn("[S] Error occurred while setting up server:" + t.getMessage()); + logMasterWarn("Error occurred while setting up server:" + t.getMessage()); t.printStackTrace(); return false; @@ -150,13 +160,13 @@ private void onText(InstanceServer.WsRecord record) var cmd = registries.createC2SCommand(text[0], text.length == 2 ? text[1] : ""); if (cmd == null) { - logger.warn("[S] Unknown command: " + text[0]); + logMasterWarn("Unknown command: " + text[0]); return; } if (!(cmd instanceof MIC2SCommand mic2s)) { - logger.warn("[S] Command is not a MIC2S instance!"); + logMasterWarn("Command is not a MIC2S instance!"); return; } @@ -183,7 +193,7 @@ private void sendCommand(WebSocket socket, MIS2CCommand command) { if (!socket.isOpen()) { - logger.warn("[S] Not sending commands to a closed socket! %s".formatted(socket.getRemoteSocketAddress())); + logMasterWarn("Not sending commands to a closed socket! %s".formatted(socket.getRemoteSocketAddress())); return; } @@ -228,7 +238,7 @@ public void onLoginCommand(MIC2SLoginCommand cProtocolCommand) return; } - logger.info("[S] '%s' is requesting a login".formatted(socket.getRemoteSocketAddress())); + logMasterInfo("'%s' is requesting a login".formatted(socket.getRemoteSocketAddress())); this.switchState(socket, ProtocolState.LOGIN); @@ -237,7 +247,7 @@ public void onLoginCommand(MIC2SLoginCommand cProtocolCommand) if (!this.level.equals(cProtocolCommand.getVersion())) { - logger.info("[S] Protocol mismatch! Disconnecting..."); + logMasterInfo("Protocol mismatch! Disconnecting..."); this.disconnect(socket, "Protocol mismatch!"); return; @@ -245,13 +255,13 @@ public void onLoginCommand(MIC2SLoginCommand cProtocolCommand) if (cProtocolCommand.getSecret() == null || !cProtocolCommand.getSecret().equals(this.secret.get())) { - logger.info("[S] Invalid secret! Disconnecting..."); + logMasterInfo("Invalid secret! Disconnecting..."); disconnect(socket, "Invalid secret '%s'".formatted(cProtocolCommand.getSecret())); return; } - logger.info("[S] '%s' logged in".formatted(socket.getRemoteSocketAddress())); + logMasterInfo("'%s' logged in".formatted(socket.getRemoteSocketAddress())); sendCommand(socket, new MIS2CLoginResultCommand(true)); switchState(socket, ProtocolState.SYNC); @@ -287,7 +297,7 @@ public void onDisguiseMetaCommand(MIC2SDisguiseMetaCommand cDisguiseMetaCommand) var meta = cDisguiseMetaCommand.getMeta(); if (meta == null || !meta.isValid()) { - logger.warn("[S] Bad client implementation? Got invalid meta from '%s'".formatted(socket.getRemoteSocketAddress())); + logMasterWarn("Bad client implementation? Got invalid meta from '%s'".formatted(socket.getRemoteSocketAddress())); return; } @@ -295,7 +305,7 @@ public void onDisguiseMetaCommand(MIC2SDisguiseMetaCommand cDisguiseMetaCommand) if (!state.loggedIn()) { - logger.warn("[S] Bad client implementation? They sent meta sync before they login! (%s)".formatted(socket.getRemoteSocketAddress())); + logMasterWarn("Bad client implementation? They sent meta sync before they login! (%s)".formatted(socket.getRemoteSocketAddress())); return; } @@ -350,8 +360,6 @@ else if (operation == Operation.REMOVE) @Override public void onMessage(InstanceServer.WsRecord wsRecord, InstanceServer server) { - if (!allowedSockets.containsKey(wsRecord.socket())) return; - this.addSchedule(() -> this.onText(wsRecord)); } diff --git a/src/main/java/xyz/nifeather/morph/network/multiInstance/slave/InstanceClient.java b/src/main/java/xyz/nifeather/morph/network/multiInstance/slave/InstanceClient.java index 945c6a46..0c5b8ea4 100644 --- a/src/main/java/xyz/nifeather/morph/network/multiInstance/slave/InstanceClient.java +++ b/src/main/java/xyz/nifeather/morph/network/multiInstance/slave/InstanceClient.java @@ -9,6 +9,8 @@ import java.net.ConnectException; import java.net.URI; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; public class InstanceClient extends WebSocketClient { @@ -33,13 +35,32 @@ private void load() { } + private void logClientInfo(String message) + { + logger.info("[C@%s] %s".formatted(Integer.toHexString(this.hashCode()), message)); + } + + private void logClientWarn(String message) + { + logger.warn("[C@%s] %s".formatted(Integer.toHexString(this.hashCode()), message)); + } + + private final AtomicBoolean disposed = new AtomicBoolean(false); + public void dispose() + { + this.disposed.set(true); + } + //region WebSocket stuffs + private final AtomicBoolean connectionAlive = new AtomicBoolean(false); + @Override public void onOpen(ServerHandshake serverHandshake) { - logger.info("[C] Opened connection to the instance server."); + logClientInfo("Opened connection to the instance server."); masterHandler.onConnectionOpen(); + connectionAlive.set(true); } @Override @@ -52,24 +73,55 @@ public void onMessage(String msg) @Override public void onClose(int code, String reason, boolean isFromRemote) { - logger.info("[C] Connection closed with code '%s' and reason '%s'".formatted(code, reason)); + logClientInfo("Connection closed with code '%s' and reason '%s'".formatted(code, reason)); + this.connectionAlive.set(false); - boolean shouldRetry = true; + boolean shouldRetry = !reason.equalsIgnoreCase("NORETRY"); var waitingSecond = 20; if (shouldRetry) { - logger.info("[C] Retrying connect after %s seconds...".formatted(waitingSecond)); - plugin.schedule(this::reconnect, waitingSecond * 20); + logClientInfo("Retrying connect after %s seconds...".formatted(waitingSecond)); + + var connectionId = this.connectionId.incrementAndGet(); + plugin.schedule(() -> tryReconnect(connectionId), waitingSecond * 20); + } + else + { + logClientInfo("Not reconnecting because either the server or other sources declared NORETRY"); } masterHandler.onConnectionClose(code); } + private void tryReconnect(int connectId) + { + if (connectionId.get() != connectId) + { + logClientInfo("Not retrying because another connection is ongoing..."); + return; + } + + this.reconnect(); + } + + private final AtomicInteger connectionId = new AtomicInteger(0); + @Override public void connect() { - logger.info("[C] Connecting to the instance server..."); + if (disposed.get()) return; + + logClientInfo("Connecting to the instance server..."); + + if (this.connectionAlive.get()) + { + logClientWarn("Already connected to the server!"); + return; + } + + connectionId.incrementAndGet(); + super.connect(); } @@ -82,19 +134,18 @@ public void onError(Exception e) } catch (Throwable t) { - logger.warn("[C] Error occurred invoking onClientError(): " + t.getMessage()); + logClientWarn("Error occurred invoking onClientError(): " + t.getMessage()); t.printStackTrace(); } if (e instanceof ConnectException) { - logger.info("[C] Can't reach the server, retrying after 30 seconds: " + e.getMessage()); - plugin.schedule(this::reconnect, 30 * 20); + logClientInfo("Can't reach the server: " + e.getMessage()); return; } - logger.error("Unknown error occurred with the client: " + e.getMessage()); + logger.error("Unknown error occurred with the client %s: %s".formatted(Integer.toHexString(this.hashCode()), e.getMessage())); e.printStackTrace(); } diff --git a/src/main/java/xyz/nifeather/morph/network/multiInstance/slave/SlaveInstance.java b/src/main/java/xyz/nifeather/morph/network/multiInstance/slave/SlaveInstance.java index d2beff71..46e7b391 100644 --- a/src/main/java/xyz/nifeather/morph/network/multiInstance/slave/SlaveInstance.java +++ b/src/main/java/xyz/nifeather/morph/network/multiInstance/slave/SlaveInstance.java @@ -43,19 +43,30 @@ private boolean stopClient() try { - client.close(CloseFrame.NORMAL); + client.close(CloseFrame.GOING_AWAY, "noRetry"); + client.dispose(); client = null; return true; } catch (Throwable t) { - logger.warn("Can't close client! " + t.getMessage()); + logSlaveWarn("Can't close client! " + t.getMessage()); t.printStackTrace(); return false; } } + private void logSlaveInfo(String message) + { + logger.info("[Slave@%s] %s".formatted(Integer.toHexString(this.hashCode()), message)); + } + + private void logSlaveWarn(String message) + { + logger.warn("[Slave@%s] %s".formatted(Integer.toHexString(this.hashCode()), message)); + } + @Resolved private MorphConfigManager config; @@ -95,7 +106,7 @@ private boolean prepareClient() } catch (Throwable t) { - logger.warn("Error occurred setting up client: " + t.getMessage()); + logSlaveWarn("Error occurred setting up client: " + t.getMessage()); t.printStackTrace(); return false; @@ -112,7 +123,7 @@ public SlaveInstance(boolean startOnLoad) @Initializer private void load() { - logger.info("Preparing multi-instance client..."); + logSlaveInfo("Preparing multi-instance client..."); config.bind(secret, ConfigOption.MASTER_SECRET); @@ -127,7 +138,7 @@ private void load() if (!prepareClient()) { - logger.warn("Can't setup client, this instance will stay offline from the instance network!"); + logSlaveWarn("Can't setup client, this instance will stay offline from the instance network!"); return; } } @@ -168,20 +179,20 @@ public void onSyncMetaCommand(MIS2CSyncMetaCommand metaCommand) { if (!currentState.get().loggedIn()) { - logger.warn("Bad server implementation? They are trying to sync meta before we login!"); + logSlaveWarn("Bad server implementation? They are trying to sync meta before we login!"); return; } var meta = metaCommand.getMeta(); if (meta == null) { - logger.warn("Bad server implementation? Get DisguiseMeta command but meta is null!"); + logSlaveWarn("Bad server implementation? Get DisguiseMeta command but meta is null!"); return; } if (!meta.isValid()) { - logger.warn("Bad server implementation? The meta is invalid!"); + logSlaveWarn("Bad server implementation? The meta is invalid!"); return; } @@ -242,11 +253,17 @@ public void onLoginResultCommand(MIS2CLoginResultCommand cLoginResultCommand) { if (currentState.get() != ProtocolState.LOGIN) { - logger.warn("[C] Bad server implementation? They sent a login result at when we are not in a login process!"); + logSlaveWarn("Bad server implementation? They sent a login result at when we are not in a login process!"); + return; + } + + if (!cLoginResultCommand.isAllowed()) + { + logSlaveWarn("Server refused the login"); return; } - if (!cLoginResultCommand.isAllowed()) return; + logSlaveInfo("Done logging in, now sending our disguise data..."); var cmds = new ObjectArrayList(); var disguises = morphManager.listAllPlayerMeta(); @@ -279,14 +296,14 @@ public void cacheRevokeStates(SocketDisguiseMeta socketDisguiseMeta) public void onStateCommand(MIS2CStateCommand cStateCommand) { if (cStateCommand.getState() == ProtocolState.INVALID) - logger.warn("[C] Bad server implementation? The new session state is invalid!"); + logSlaveWarn("Bad server implementation? The new session state is invalid!"); switchState(cStateCommand.getState()); } private void switchState(ProtocolState newState) { - logger.info("[C] Client networking state switched to " + newState); + logSlaveInfo("Client networking state switched to " + newState); currentState.set(newState); } @@ -329,13 +346,13 @@ private void onCommandRaw(String raw) var cmd = registries.createS2CCommand(text[0], text.length == 2 ? text[1] : ""); if (cmd == null) { - logger.warn("[C] Unknown command: " + text[0]); + logSlaveWarn("Unknown command: " + text[0]); return; } if (!(cmd instanceof MIS2CCommand mis2c)) { - logger.warn("[C] Command '%s' is not a MIS2C instance!".formatted(cmd)); + logSlaveWarn("Command '%s' is not a MIS2C instance!".formatted(cmd)); return; } From be3d2c8afdd68f1e41f4e9ecf1e4fa935d87c798 Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Thu, 7 Nov 2024 00:15:41 +0800 Subject: [PATCH 4/8] huh --- .../impl/HealsFromEntityAbility.java | 4 +++- .../nifeather/morph/misc/SoundHandler.java | 2 +- .../morph/utilities/EntityTypeUtils.java | 24 ++++++++++++++----- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/HealsFromEntityAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/HealsFromEntityAbility.java index c64e15b3..86494d52 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/impl/HealsFromEntityAbility.java +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/HealsFromEntityAbility.java @@ -186,7 +186,9 @@ private Entity findEntity(NmsRecord record, EntityType nmsType, double expand var boundingBox = nmsType.getDimensions().makeBoundingBox(player.position()); - Class classType = EntityTypeUtils.getNmsClass(bukkitType, record.nmsPlayer().getBukkitEntity().getWorld()); + Class classType = EntityTypeUtils.getNmsClass(bukkitType, + record.nmsPlayer().getBukkitEntity().getWorld(), + record.nmsPlayer().getBukkitEntity().getLocation()); if (classType == null) return null; diff --git a/src/main/java/xyz/nifeather/morph/misc/SoundHandler.java b/src/main/java/xyz/nifeather/morph/misc/SoundHandler.java index dd5e917a..d34bfe72 100644 --- a/src/main/java/xyz/nifeather/morph/misc/SoundHandler.java +++ b/src/main/java/xyz/nifeather/morph/misc/SoundHandler.java @@ -112,7 +112,7 @@ public void refreshSounds(EntityType entityType, boolean isBaby) soundFrequency = MathUtils.clamp(0, 2, config.getBindable(Double.class, ConfigOption.AMBIENT_FREQUENCY).get()); - var soundEvent = EntityTypeUtils.getAmbientSound(entityType, this.bindingPlayer.getWorld()); + var soundEvent = EntityTypeUtils.getAmbientSound(entityType, this.bindingPlayer.getWorld(), this.bindingPlayer.getLocation()); var sound = soundEvent.sound(); if (sound == null) return; diff --git a/src/main/java/xyz/nifeather/morph/utilities/EntityTypeUtils.java b/src/main/java/xyz/nifeather/morph/utilities/EntityTypeUtils.java index 546c0f19..90e82938 100644 --- a/src/main/java/xyz/nifeather/morph/utilities/EntityTypeUtils.java +++ b/src/main/java/xyz/nifeather/morph/utilities/EntityTypeUtils.java @@ -11,8 +11,10 @@ import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.player.Player; +import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.World; +import org.bukkit.block.Block; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.entity.Enemy; import org.bukkit.entity.EntityType; @@ -61,15 +63,25 @@ public record SoundInfo(@Nullable SoundEvent sound, SoundSource source, int inte // Hope this will work with Folia // I guess it will... - public static T createEntityThenDispose(net.minecraft.world.entity.EntityType nmsType, World world) + // + // Requiring spawn location because Folia has a bug where loading chunks will stuck the whole region thread... + // So we require a specific value that matches the player's current location, hopefully could prevent chunk loading. + @Nullable + public static T createEntityThenDispose(net.minecraft.world.entity.EntityType nmsType, World world, Location spawnLocation) { + spawnLocation = spawnLocation.clone(); + var serverWorld = ((CraftWorld) world).getHandle(); + spawnLocation.setY(-4096); + + var locationBlock = spawnLocation.toBlockLocation(); + var spawnBlockLocation = new BlockPos(locationBlock.getBlockX(), locationBlock.getBlockY(), locationBlock.getBlockZ()); - return nmsType.create(serverWorld, EntityTypeUtils::scheduleEntityDiscard, BlockPos.ZERO, MobSpawnType.COMMAND, false, false); + return nmsType.create(serverWorld, EntityTypeUtils::scheduleEntityDiscard, spawnBlockLocation, MobSpawnType.COMMAND, false, false); } @NotNull - public static SoundInfo getAmbientSound(EntityType bukkitType, World tickingWorld) + public static SoundInfo getAmbientSound(EntityType bukkitType, World tickingWorld, Location tickingLocation) { if (bukkitType == EntityType.UNKNOWN) return new SoundInfo(null, SoundSource.PLAYERS, Integer.MAX_VALUE, 1); @@ -77,7 +89,7 @@ public static SoundInfo getAmbientSound(EntityType bukkitType, World tickingWorl var cache = typeSoundMap.getOrDefault(bukkitType, null); if (cache != null) return cache; - var entity = createEntityThenDispose(getNmsType(bukkitType), tickingWorld); + var entity = createEntityThenDispose(getNmsType(bukkitType), tickingWorld, tickingLocation); if (entity instanceof Mob mob) { @@ -113,7 +125,7 @@ public static net.minecraft.world.entity.EntityType getNmsType(@NotNull Entit } @Nullable - public static Class getNmsClass(@NotNull EntityType type, World tickingWorld) + public static Class getNmsClass(@NotNull EntityType type, World tickingWorld, Location tickingLocation) { var cache = nmsClassMap.getOrDefault(type, null); if (cache != null) return cache; @@ -127,7 +139,7 @@ public static Class getNmsClass(@NotNull EntityType type, Worl return null; } - var entity = createEntityThenDispose(nmsType, tickingWorld); + var entity = createEntityThenDispose(nmsType, tickingWorld, tickingLocation); if (entity == null) { From 0a1f49fff87405f9eaf4f6b0159bd233f716cbad Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Thu, 7 Nov 2024 11:56:24 +0800 Subject: [PATCH 5/8] misc: Improve(and fix?) PAPI support --- .../placeholderapi/IPlaceholderProvider.java | 6 --- .../placeholderapi/MatchMode.java | 17 --------- .../PlaceholderIntegration.java | 29 ++++++++------ .../builtin/AvaliableDisguisesProvider.java | 38 +++++++++---------- .../builtin/StateNameProvider.java | 35 ++++++++--------- 5 files changed, 52 insertions(+), 73 deletions(-) delete mode 100644 src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/MatchMode.java diff --git a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/IPlaceholderProvider.java b/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/IPlaceholderProvider.java index f94b3875..20f5fe7c 100644 --- a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/IPlaceholderProvider.java +++ b/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/IPlaceholderProvider.java @@ -22,10 +22,4 @@ public interface IPlaceholderProvider */ @Nullable public String resolvePlaceholder(Player player, String params); - - /** - * 获取ID的匹配模式 - * @return {@link MatchMode} - */ - public MatchMode getMatchMode(); } diff --git a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/MatchMode.java b/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/MatchMode.java deleted file mode 100644 index a9621e4e..00000000 --- a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/MatchMode.java +++ /dev/null @@ -1,17 +0,0 @@ -package xyz.nifeather.morph.misc.integrations.placeholderapi; - -/** - * ID匹配模式 - */ -public enum MatchMode -{ - /** - * 精准匹配 - */ - Exact, - - /** - * 只需要以某个字符串开头即可 - */ - Prefixes -} diff --git a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/PlaceholderIntegration.java b/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/PlaceholderIntegration.java index a8347843..f6d00cf7 100644 --- a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/PlaceholderIntegration.java +++ b/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/PlaceholderIntegration.java @@ -5,6 +5,8 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import xiamomc.pluginbase.Managers.DependencyManager; import xyz.nifeather.morph.misc.integrations.placeholderapi.builtin.AvaliableDisguisesProvider; import xyz.nifeather.morph.misc.integrations.placeholderapi.builtin.StateNameProvider; @@ -14,6 +16,7 @@ public class PlaceholderIntegration extends PlaceholderExpansion { private static final List providers = new ObjectArrayList<>(); + private static final Logger log = LoggerFactory.getLogger(PlaceholderIntegration.class); public PlaceholderIntegration(DependencyManager depManager) { @@ -26,7 +29,7 @@ public PlaceholderIntegration(DependencyManager depManager) @Override public @NotNull String getIdentifier() { - return "morph"; + return "feathermorph"; } @Override @@ -38,7 +41,7 @@ public PlaceholderIntegration(DependencyManager depManager) @Override public @NotNull String getVersion() { - return "1.0.10"; + return "1.4.0"; } private void addPlaceholders(List providerList) @@ -56,7 +59,7 @@ public boolean addPlaceholderProvider(IPlaceholderProvider provider) if (providers.stream().anyMatch(p -> providerEquals(p, provider))) return false; - providers.add(0, provider); + providers.addFirst(provider); return true; } @@ -64,26 +67,28 @@ private boolean providerEquals(IPlaceholderProvider source, IPlaceholderProvider { if (source == null || target == null) return false; - return source.getMatchMode() == target.getMatchMode() - && source.getPlaceholderIdentifier().equals(target.getPlaceholderIdentifier()); + return source.getPlaceholderIdentifier().equals(target.getPlaceholderIdentifier()); } - private final String defaultString = "???"; + private static final String defaultString = "???"; @Override - public @Nullable String onPlaceholderRequest(Player player, @NotNull String params) + public @Nullable String onPlaceholderRequest(Player player, @NotNull String param) { if (player == null) return defaultString; + param = param.replaceFirst(getIdentifier() + "_", ""); + var paramSpilt = param.split("_", 2); + + if (paramSpilt.length != 2) + return null; + var provider = providers.stream() - .filter(p -> p.getMatchMode() == MatchMode.Exact - ? params.equalsIgnoreCase(p.getPlaceholderIdentifier()) - : params.startsWith(p.getPlaceholderIdentifier())) + .filter(p -> p.getPlaceholderIdentifier().equalsIgnoreCase(paramSpilt[0])) .findFirst().orElse(null); if (provider == null) return defaultString; - var val = provider.resolvePlaceholder(player, params); - return val == null ? defaultString : val; + return provider.resolvePlaceholder(player, paramSpilt[1]); } } diff --git a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/builtin/AvaliableDisguisesProvider.java b/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/builtin/AvaliableDisguisesProvider.java index 20f361f0..495ada2e 100644 --- a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/builtin/AvaliableDisguisesProvider.java +++ b/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/builtin/AvaliableDisguisesProvider.java @@ -9,51 +9,47 @@ import xyz.nifeather.morph.interfaces.IManagePlayerData; import xyz.nifeather.morph.messages.MessageUtils; import xyz.nifeather.morph.misc.integrations.placeholderapi.IPlaceholderProvider; -import xyz.nifeather.morph.misc.integrations.placeholderapi.MatchMode; public class AvaliableDisguisesProvider extends MorphPluginObject implements IPlaceholderProvider { @Override public @NotNull String getPlaceholderIdentifier() { - return "avaliable"; + return "available"; } @Resolved private IManagePlayerData data; @Override - public @Nullable String resolvePlaceholder(Player player, String params) + public @Nullable String resolvePlaceholder(Player player, String param) { - var type = params.replace(getPlaceholderIdentifier(), ""); var builder = new StringBuilder(); var list = data.getAvaliableDisguisesFor(player); var locale = MessageUtils.getServerLocale(); - if (type.equalsIgnoreCase("_name")) + switch (param) { - list.forEach(i -> + case "name" -> { - builder.append(PlainTextComponentSerializer.plainText().serialize(i.asComponent(locale))); + list.forEach(i -> + { + builder.append(PlainTextComponentSerializer.plainText().serialize(i.asComponent(locale))); - if (list.iterator().hasNext()) - builder.append(", "); - }); + if (list.iterator().hasNext()) + builder.append(", "); + }); - return builder.toString(); - } - else if (type.equalsIgnoreCase("_count")) - { - return String.valueOf(list.size()); + return builder.toString(); + } + + case "count" -> + { + return String.valueOf(list.size()); + } } return null; } - - @Override - public MatchMode getMatchMode() - { - return MatchMode.Prefixes; - } } diff --git a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/builtin/StateNameProvider.java b/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/builtin/StateNameProvider.java index bd8f264f..b0a440f0 100644 --- a/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/builtin/StateNameProvider.java +++ b/src/main/java/xyz/nifeather/morph/misc/integrations/placeholderapi/builtin/StateNameProvider.java @@ -8,7 +8,6 @@ import xyz.nifeather.morph.MorphManager; import xyz.nifeather.morph.MorphPluginObject; import xyz.nifeather.morph.misc.integrations.placeholderapi.IPlaceholderProvider; -import xyz.nifeather.morph.misc.integrations.placeholderapi.MatchMode; public class StateNameProvider extends MorphPluginObject implements IPlaceholderProvider { @@ -22,30 +21,32 @@ public class StateNameProvider extends MorphPluginObject implements IPlaceholder private MorphManager morphs; @Override - public @Nullable String resolvePlaceholder(Player player, String params) + public @Nullable String resolvePlaceholder(Player player, String param) { - var type = params.replace(getPlaceholderIdentifier(), ""); var state = morphs.getDisguiseStateFor(player); - if (type.equalsIgnoreCase("_id")) + switch (param) { - return state != null - ? state.getDisguiseIdentifier() - : "???"; - } - else if (type.equalsIgnoreCase("_name")) - { - return state != null + case "id" -> + { + return state != null + ? state.getDisguiseIdentifier() + : "???"; + } + + case "name" -> + { + return state != null ? PlainTextComponentSerializer.plainText().serialize(state.getServerDisplay()) : "???"; + } + + case "status" -> + { + return state != null ? "true" : "false"; + } } return null; } - - @Override - public MatchMode getMatchMode() - { - return MatchMode.Prefixes; - } } From 4f9fd5c90f0dae19cdbb3648dccfe21ba51e88a3 Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Sun, 10 Nov 2024 20:29:47 +0800 Subject: [PATCH 6/8] misc: Monitor on the event --- .../morph/abilities/impl/OnAttackAbility.java | 3 ++- .../impl/onAttack/ExtraKnockbackAbility.java | 15 --------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/OnAttackAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/OnAttackAbility.java index 10caae26..1400d993 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/impl/OnAttackAbility.java +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/OnAttackAbility.java @@ -3,13 +3,14 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageByEntityEvent; import xyz.nifeather.morph.abilities.MorphAbility; import xyz.nifeather.morph.storage.skill.ISkillOption; public abstract class OnAttackAbility extends MorphAbility { - @EventHandler(ignoreCancelled = true) + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) public void onEntityDamagedByEntity(EntityDamageByEntityEvent e) { if (!(e.getDamager() instanceof Player player)) return; diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/onAttack/ExtraKnockbackAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/onAttack/ExtraKnockbackAbility.java index 2d432dae..ec237f3f 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/impl/onAttack/ExtraKnockbackAbility.java +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/onAttack/ExtraKnockbackAbility.java @@ -25,21 +25,6 @@ public class ExtraKnockbackAbility extends OnAttackAbility return AbilityType.EXTRA_KNOCKBACK; } - /* - @EventHandler - private void onGolemDmg(EntityDamageByEntityEvent e) - { - if (!(e.getDamager() instanceof CraftIronGolem craftIronGolem)) return; - if (!(e.getEntity() instanceof CraftPlayer craftPlayer)) return; - - logger.info("VECTOR: %s".formatted(craftPlayer.getHandle().getDeltaMovement())); - this.addSchedule(() -> - { - logger.info("SCHED VECTOR: %s".formatted(craftPlayer.getHandle().getDeltaMovement())); - }); - } - */ - @Resolved(shouldSolveImmediately = true) private MorphManager manager; From 3ae6f93f11ceca95dd48aaa2d6a955e1f8a2974b Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Mon, 11 Nov 2024 21:18:07 +0800 Subject: [PATCH 7/8] oops --- .../morph/abilities/impl/AttributeModifyingAbility.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/AttributeModifyingAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/AttributeModifyingAbility.java index 423ffb66..fedd1758 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/impl/AttributeModifyingAbility.java +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/AttributeModifyingAbility.java @@ -56,8 +56,10 @@ public boolean applyToPlayer(Player player, DisguiseState state) var operationType = modifierOption.operationType.toBukkitOperation(); if (operationType == null) { - logger.warn(""); - return false; + logger.warn("Modifier operation not set for attribute %s of disguise %s, ignoring...".formatted( + modifierOption.attributeName, state.getDisguiseIdentifier() + )); + continue; } var modifier = new AttributeModifier(modifierKey, modifierOption.value, From 5b67a8241f8488647247570964e7c5502b41a5f7 Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Wed, 13 Nov 2024 11:14:55 +0800 Subject: [PATCH 8/8] =?UTF-8?q?add:=20=E6=B7=BB=E5=8A=A0=E9=99=90=E5=88=B6?= =?UTF-8?q?=E5=87=8B=E9=9B=B6=E4=BC=A4=E5=AE=B3=E7=9A=84=E8=A2=AB=E5=8A=A8?= =?UTF-8?q?=E6=8A=80=E8=83=BD=20misc:=20=E4=B8=80=E4=BA=9B=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../morph/abilities/AbilityManager.java | 4 ++ .../morph/abilities/AbilityType.java | 6 ++- .../impl/AttributeModifyingAbility.java | 3 +- .../morph/abilities/impl/BossbarAbility.java | 4 +- .../abilities/impl/DamageReducingAbility.java | 3 ++ .../ReduceFallDamageAbility.java | 3 +- .../ReduceMagicDamageAbility.java | 3 +- .../dmgReduce/ReduceWitherDamageAbility.java | 29 +++++++++++++++ .../morph/skills/DefaultConfigGenerator.java | 6 ++- .../skill/SkillsConfigurationStoreNew.java | 37 ++++++++++++++++++- 10 files changed, 88 insertions(+), 10 deletions(-) rename src/main/java/xyz/nifeather/morph/abilities/impl/{ => dmgReduce}/ReduceFallDamageAbility.java (85%) rename src/main/java/xyz/nifeather/morph/abilities/impl/{ => dmgReduce}/ReduceMagicDamageAbility.java (85%) create mode 100644 src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceWitherDamageAbility.java diff --git a/src/main/java/xyz/nifeather/morph/abilities/AbilityManager.java b/src/main/java/xyz/nifeather/morph/abilities/AbilityManager.java index 4c677698..cf45fb3b 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/AbilityManager.java +++ b/src/main/java/xyz/nifeather/morph/abilities/AbilityManager.java @@ -10,6 +10,9 @@ import xyz.nifeather.morph.MorphManager; import xyz.nifeather.morph.MorphPluginObject; import xyz.nifeather.morph.abilities.impl.*; +import xyz.nifeather.morph.abilities.impl.dmgReduce.ReduceFallDamageAbility; +import xyz.nifeather.morph.abilities.impl.dmgReduce.ReduceMagicDamageAbility; +import xyz.nifeather.morph.abilities.impl.dmgReduce.ReduceWitherDamageAbility; import xyz.nifeather.morph.abilities.impl.potion.*; import xyz.nifeather.morph.abilities.impl.onAttack.ExtraKnockbackAbility; import xyz.nifeather.morph.abilities.impl.onAttack.PotionOnAttackAbility; @@ -96,6 +99,7 @@ private void load() new NoFallDamageAbility(), new ReduceFallDamageAbility(), new ReduceMagicDamageAbility(), + new ReduceWitherDamageAbility(), new SmallJumpBoostAbility(), new SnowyAbility(), new SpeedBoostAbility(), diff --git a/src/main/java/xyz/nifeather/morph/abilities/AbilityType.java b/src/main/java/xyz/nifeather/morph/abilities/AbilityType.java index cd82c09d..7e737b33 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/AbilityType.java +++ b/src/main/java/xyz/nifeather/morph/abilities/AbilityType.java @@ -20,8 +20,6 @@ public class AbilityType public static final NamespacedKey HAS_FEATHER_FALLING = new NamespacedKey(nameSpace, "feather_falling"); public static final NamespacedKey NO_FALL_DAMAGE = new NamespacedKey(nameSpace, "no_fall_damage"); - public static final NamespacedKey REDUCES_FALL_DAMAGE = new NamespacedKey(nameSpace, "reduce_fall_damage"); - public static final NamespacedKey REDUCES_MAGIC_DAMAGE = new NamespacedKey(nameSpace, "reduce_magic_damage"); public static final NamespacedKey SNOWY = new NamespacedKey(nameSpace, "snowy"); public static final NamespacedKey WARDEN_LESS_AWARE = new NamespacedKey(nameSpace, "warden_less_aware"); public static final NamespacedKey WARDEN = new NamespacedKey(nameSpace, "warden"); @@ -34,4 +32,8 @@ public class AbilityType public static final NamespacedKey DRYOUT_IN_AIR = new NamespacedKey(nameSpace, "dryout_in_air"); public static final NamespacedKey POTION_ON_ATTACK = new NamespacedKey(nameSpace, "potion_on_attack"); public static final NamespacedKey SPIDER = new NamespacedKey(nameSpace, "spider"); + + public static final NamespacedKey REDUCES_FALL_DAMAGE = new NamespacedKey(nameSpace, "reduce_fall_damage"); + public static final NamespacedKey REDUCES_MAGIC_DAMAGE = new NamespacedKey(nameSpace, "reduce_magic_damage"); + public static final NamespacedKey REDUCES_WITHER_DAMAGE = new NamespacedKey(nameSpace, "reduce_wither_damage"); } diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/AttributeModifyingAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/AttributeModifyingAbility.java index fedd1758..82e6a5a1 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/impl/AttributeModifyingAbility.java +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/AttributeModifyingAbility.java @@ -62,8 +62,7 @@ public boolean applyToPlayer(Player player, DisguiseState state) continue; } - var modifier = new AttributeModifier(modifierKey, modifierOption.value, - operationType, EquipmentSlotGroup.ANY); + var modifier = new AttributeModifier(modifierKey, modifierOption.value, operationType); attributeInstance.removeModifier(modifierKey); attributeInstance.addModifier(modifier); diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/BossbarAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/BossbarAbility.java index 0a6a3d75..53433329 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/impl/BossbarAbility.java +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/BossbarAbility.java @@ -25,12 +25,12 @@ public class BossbarAbility extends MorphAbility { - private Bindable allowBossbar; + private final Bindable allowBossbar = new Bindable<>(false); @Initializer private void load(MorphConfigManager configManager) { - allowBossbar = configManager.getBindable(Boolean.class, ConfigOption.DISPLAY_BOSSBAR); + configManager.bind(allowBossbar, ConfigOption.DISPLAY_BOSSBAR); } @Override diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/DamageReducingAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/DamageReducingAbility.java index 1e480ea4..54ab2cbd 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/impl/DamageReducingAbility.java +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/DamageReducingAbility.java @@ -40,5 +40,8 @@ public void onPlayerTookDamage(EntityDamageEvent e) : damage - dmgOption.getReduceAmount(); e.setDamage(Math.max(0d, damage)); + + if (damage <= 0d) + e.setCancelled(true); } } diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/ReduceFallDamageAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceFallDamageAbility.java similarity index 85% rename from src/main/java/xyz/nifeather/morph/abilities/impl/ReduceFallDamageAbility.java rename to src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceFallDamageAbility.java index c7d277c1..6585aca7 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/impl/ReduceFallDamageAbility.java +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceFallDamageAbility.java @@ -1,9 +1,10 @@ -package xyz.nifeather.morph.abilities.impl; +package xyz.nifeather.morph.abilities.impl.dmgReduce; import org.bukkit.NamespacedKey; import org.bukkit.event.entity.EntityDamageEvent; import org.jetbrains.annotations.NotNull; import xyz.nifeather.morph.abilities.AbilityType; +import xyz.nifeather.morph.abilities.impl.DamageReducingAbility; import xyz.nifeather.morph.abilities.options.ReduceDamageOption; public class ReduceFallDamageAbility extends DamageReducingAbility diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/ReduceMagicDamageAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceMagicDamageAbility.java similarity index 85% rename from src/main/java/xyz/nifeather/morph/abilities/impl/ReduceMagicDamageAbility.java rename to src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceMagicDamageAbility.java index 5e14172f..afd1bf62 100644 --- a/src/main/java/xyz/nifeather/morph/abilities/impl/ReduceMagicDamageAbility.java +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceMagicDamageAbility.java @@ -1,9 +1,10 @@ -package xyz.nifeather.morph.abilities.impl; +package xyz.nifeather.morph.abilities.impl.dmgReduce; import org.bukkit.NamespacedKey; import org.bukkit.event.entity.EntityDamageEvent; import org.jetbrains.annotations.NotNull; import xyz.nifeather.morph.abilities.AbilityType; +import xyz.nifeather.morph.abilities.impl.DamageReducingAbility; import xyz.nifeather.morph.abilities.options.ReduceDamageOption; public class ReduceMagicDamageAbility extends DamageReducingAbility diff --git a/src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceWitherDamageAbility.java b/src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceWitherDamageAbility.java new file mode 100644 index 00000000..53643bca --- /dev/null +++ b/src/main/java/xyz/nifeather/morph/abilities/impl/dmgReduce/ReduceWitherDamageAbility.java @@ -0,0 +1,29 @@ +package xyz.nifeather.morph.abilities.impl.dmgReduce; + +import org.bukkit.NamespacedKey; +import org.bukkit.event.entity.EntityDamageEvent; +import org.jetbrains.annotations.NotNull; +import xyz.nifeather.morph.abilities.AbilityType; +import xyz.nifeather.morph.abilities.impl.DamageReducingAbility; +import xyz.nifeather.morph.abilities.options.ReduceDamageOption; + +public class ReduceWitherDamageAbility extends DamageReducingAbility +{ + @Override + protected EntityDamageEvent.DamageCause getTargetCause() + { + return EntityDamageEvent.DamageCause.WITHER; + } + + @Override + protected @NotNull ReduceDamageOption createOption() + { + return new ReduceDamageOption(); + } + + @Override + public @NotNull NamespacedKey getIdentifier() + { + return AbilityType.REDUCES_WITHER_DAMAGE; + } +} diff --git a/src/main/java/xyz/nifeather/morph/skills/DefaultConfigGenerator.java b/src/main/java/xyz/nifeather/morph/skills/DefaultConfigGenerator.java index e04ad4a8..919ce853 100644 --- a/src/main/java/xyz/nifeather/morph/skills/DefaultConfigGenerator.java +++ b/src/main/java/xyz/nifeather/morph/skills/DefaultConfigGenerator.java @@ -281,8 +281,12 @@ public void generateAbilities() this.getConfiguration(EntityType.WITHER_SKELETON) .addAbilityIdentifier(AbilityType.POTION_ON_ATTACK) + .addAbilityIdentifier(AbilityType.REDUCES_WITHER_DAMAGE) + .addAbilityIdentifier(AbilityType.HAS_FIRE_RESISTANCE) .appendOption(AbilityType.POTION_ON_ATTACK, - PotionEffectOption.from(PotionEffectType.WITHER, 10 * 20, 0)); + PotionEffectOption.from(PotionEffectType.WITHER, 10 * 20, 0)) + .appendOption(AbilityType.REDUCES_WITHER_DAMAGE, + new ReduceDamageOption(1, true)); this.getConfiguration(EntityType.HUSK) .addAbilityIdentifier(AbilityType.POTION_ON_ATTACK) diff --git a/src/main/java/xyz/nifeather/morph/storage/skill/SkillsConfigurationStoreNew.java b/src/main/java/xyz/nifeather/morph/storage/skill/SkillsConfigurationStoreNew.java index 2a850ba8..9a374ed1 100644 --- a/src/main/java/xyz/nifeather/morph/storage/skill/SkillsConfigurationStoreNew.java +++ b/src/main/java/xyz/nifeather/morph/storage/skill/SkillsConfigurationStoreNew.java @@ -1,9 +1,12 @@ package xyz.nifeather.morph.storage.skill; import org.apache.commons.io.FileUtils; +import org.bukkit.entity.EntityType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import xiamomc.pluginbase.Annotations.Initializer; +import xyz.nifeather.morph.abilities.AbilityType; +import xyz.nifeather.morph.abilities.options.ReduceDamageOption; import xyz.nifeather.morph.skills.DefaultConfigGenerator; import xyz.nifeather.morph.storage.DirectoryJsonBasedStorage; import xyz.nifeather.morph.storage.MorphJsonBasedStorage; @@ -11,6 +14,7 @@ import java.io.File; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.util.concurrent.atomic.AtomicBoolean; public class SkillsConfigurationStoreNew extends DirectoryJsonBasedStorage { @@ -26,9 +30,12 @@ private void load() if (packageVersion < TARGET_PACKAGE_VERSION) update(packageVersion); + + if (packageVersion > TARGET_PACKAGE_VERSION) + logger.warn("The package version is newer than our implementation! Errors may occur!"); } - private static final int TARGET_PACKAGE_VERSION = PackageVersions.INITIAL; + private static final int TARGET_PACKAGE_VERSION = PackageVersions.WITHER_SKELETON_CHANGES; private void update(int currentVersion) { @@ -42,6 +49,11 @@ private void update(int currentVersion) saveDefaultGeneratedConfigurations(); } + if (currentVersion < PackageVersions.WITHER_SKELETON_CHANGES) + { + migrateWitherSkeleton(); + } + setPackageVersion(TARGET_PACKAGE_VERSION); } @@ -79,6 +91,28 @@ private void migrateFromLegacyStorage() } } + private void migrateWitherSkeleton() + { + logger.info("Migrating new Wither Skeleton configuration"); + + var configuration = this.get(EntityType.WITHER_SKELETON.key().asString()); + if (configuration == null) + { + logger.info("No configuration present for minecraft:wither_skeleton, skipping..."); + return; + } + + configuration.addAbilityIdentifier(AbilityType.HAS_FIRE_RESISTANCE) + .addAbilityIdentifier(AbilityType.REDUCES_WITHER_DAMAGE) + .appendOption(AbilityType.REDUCES_WITHER_DAMAGE, + new ReduceDamageOption(1, true)); + + configuration.legacy_MobID = EntityType.WITHER_SKELETON.key().asString(); + this.save(configuration); + + logger.info("Done Migrating new Wither Skeleton configuration"); + } + private void saveDefaultGeneratedConfigurations() { logger.info("Saving default generated skill configurations..."); @@ -166,5 +200,6 @@ public SkillAbilityConfigurationContainer getStoring() public static class PackageVersions { public static final int INITIAL = 1; + public static final int WITHER_SKELETON_CHANGES = 2; } }