diff --git a/core/src/main/java/com/nisovin/magicspells/spelleffects/effecttypes/GameTestAddMarkerEffect.java b/core/src/main/java/com/nisovin/magicspells/spelleffects/effecttypes/GameTestAddMarkerEffect.java new file mode 100644 index 000000000..4ea79497a --- /dev/null +++ b/core/src/main/java/com/nisovin/magicspells/spelleffects/effecttypes/GameTestAddMarkerEffect.java @@ -0,0 +1,118 @@ +package com.nisovin.magicspells.spelleffects.effecttypes; + +import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.configuration.ConfigurationSection; + +import com.nisovin.magicspells.MagicSpells; +import com.nisovin.magicspells.util.SpellData; +import com.nisovin.magicspells.util.config.ConfigData; +import com.nisovin.magicspells.spelleffects.SpellEffect; +import com.nisovin.magicspells.util.config.ConfigDataUtil; + +public class GameTestAddMarkerEffect extends SpellEffect { + + private ConfigData color; + private ConfigData name; + private ConfigData lifetime; + private ConfigData broadcast; + private ConfigData viewer; + private ConfigData useViewerAsTarget; + private ConfigData useViewerAsDefault; + + @Override + protected void loadFromConfig(ConfigurationSection config) { + name = ConfigDataUtil.getString(config, "name", ""); + color = ConfigDataUtil.getARGBColor(config, "color", Color.BLACK); + viewer = ConfigDataUtil.getEnum(config, "viewer", MarkerViewer.class, MarkerViewer.POSITION); + lifetime = ConfigDataUtil.getInteger(config, "lifetime", 1000); + broadcast = ConfigDataUtil.getBoolean(config, "broadcast", false); + useViewerAsTarget = ConfigDataUtil.getBoolean(config, "use-viewer-as-target", false); + useViewerAsDefault = ConfigDataUtil.getBoolean(config, "use-viewer-as-default", true); + } + + @Override + protected Runnable playEffectLocation(Location location, SpellData data) { + if (broadcast.get(data)) { + broadcast(location, data); + return null; + } + + Player viewer = switch (this.viewer.get(data)) { + case CASTER -> data.caster() instanceof Player p ? p : null; + case TARGET -> data.target() instanceof Player p ? p : null; + case POSITION -> null; + }; + if (viewer == null) return null; + + String name = this.name.get(data); + Color color = this.color.get(data); + int lifetime = this.lifetime.get(data); + MagicSpells.getVolatileCodeHandler().addGameTestMarker(viewer, location, color.asARGB(), name, lifetime); + + return null; + } + + @Override + protected Runnable playEffectEntity(Entity entity, SpellData data) { + if (broadcast.get(data)) { + broadcast(entity.getLocation(), data); + return null; + } + + Player viewer = switch (this.viewer.get(data)) { + case CASTER -> data.caster() instanceof Player p ? p : null; + case TARGET -> data.target() instanceof Player p ? p : null; + case POSITION -> entity instanceof Player p ? p : null; + }; + if (viewer == null) return null; + + String name = this.name.get(data); + Color color = this.color.get(data); + int lifetime = this.lifetime.get(data); + MagicSpells.getVolatileCodeHandler().addGameTestMarker(viewer, entity.getLocation(), color.asARGB(), name, lifetime); + + return null; + } + + private void broadcast(Location location, SpellData data) { + boolean useViewerAsTarget = this.useViewerAsTarget.get(data); + boolean useViewerAsDefault = this.useViewerAsDefault.get(data); + + String name = null; + Color color = null; + int lifetime = 0; + + if (!useViewerAsTarget && !useViewerAsDefault) { + name = this.name.get(data); + color = this.color.get(data); + lifetime = this.lifetime.get(data); + } + + for (Player viewer : location.getWorld().getPlayers()) { + if (useViewerAsTarget || useViewerAsDefault) { + SpellData spellData = data; + if (useViewerAsTarget) spellData = spellData.target(viewer); + if (useViewerAsDefault) spellData = spellData.recipient(viewer); + + name = this.name.get(spellData); + color = this.color.get(spellData); + lifetime = this.lifetime.get(spellData); + } + + MagicSpells.getVolatileCodeHandler().addGameTestMarker(viewer, location, color.asARGB(), name, lifetime); + } + } + + private enum MarkerViewer { + + CASTER, + TARGET, + POSITION + + } + +} diff --git a/core/src/main/java/com/nisovin/magicspells/spelleffects/effecttypes/GameTestClearMarkersEffect.java b/core/src/main/java/com/nisovin/magicspells/spelleffects/effecttypes/GameTestClearMarkersEffect.java new file mode 100644 index 000000000..8ccf60e6c --- /dev/null +++ b/core/src/main/java/com/nisovin/magicspells/spelleffects/effecttypes/GameTestClearMarkersEffect.java @@ -0,0 +1,75 @@ +package com.nisovin.magicspells.spelleffects.effecttypes; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.configuration.ConfigurationSection; + +import com.nisovin.magicspells.MagicSpells; +import com.nisovin.magicspells.util.SpellData; +import com.nisovin.magicspells.util.config.ConfigData; +import com.nisovin.magicspells.spelleffects.SpellEffect; +import com.nisovin.magicspells.util.config.ConfigDataUtil; + +public class GameTestClearMarkersEffect extends SpellEffect { + + private ConfigData broadcast; + private ConfigData viewer; + + @Override + protected void loadFromConfig(ConfigurationSection config) { + viewer = ConfigDataUtil.getEnum(config, "viewer", MarkerViewer.class, MarkerViewer.POSITION); + broadcast = ConfigDataUtil.getBoolean(config, "broadcast", false); + } + + @Override + protected Runnable playEffectLocation(Location location, SpellData data) { + if (broadcast.get(data)) { + for (Player viewer : location.getWorld().getPlayers()) + MagicSpells.getVolatileCodeHandler().clearGameTestMarkers(viewer); + + return null; + } + + Player viewer = switch (this.viewer.get(data)) { + case CASTER -> data.caster() instanceof Player p ? p : null; + case TARGET -> data.target() instanceof Player p ? p : null; + case POSITION -> null; + }; + if (viewer == null) return null; + + MagicSpells.getVolatileCodeHandler().clearGameTestMarkers(viewer); + + return null; + } + + @Override + protected Runnable playEffectEntity(Entity entity, SpellData data) { + if (broadcast.get(data)) { + for (Player viewer : entity.getWorld().getPlayers()) + MagicSpells.getVolatileCodeHandler().clearGameTestMarkers(viewer); + + return null; + } + + Player viewer = switch (this.viewer.get(data)) { + case CASTER -> data.caster() instanceof Player p ? p : null; + case TARGET -> data.target() instanceof Player p ? p : null; + case POSITION -> entity instanceof Player p ? p : null; + }; + if (viewer == null) return null; + + MagicSpells.getVolatileCodeHandler().clearGameTestMarkers(viewer); + + return null; + } + + private enum MarkerViewer { + + CASTER, + TARGET, + POSITION + + } + +} diff --git a/core/src/main/java/com/nisovin/magicspells/util/managers/SpellEffectManager.java b/core/src/main/java/com/nisovin/magicspells/util/managers/SpellEffectManager.java index 9c3d83c75..42dc1bc4c 100644 --- a/core/src/main/java/com/nisovin/magicspells/util/managers/SpellEffectManager.java +++ b/core/src/main/java/com/nisovin/magicspells/util/managers/SpellEffectManager.java @@ -55,6 +55,8 @@ private void initialize() { addSpellEffect("entity", EntityEffect.class); addSpellEffect("explosion", ExplosionEffect.class); addSpellEffect("fireworks", FireworksEffect.class); + addSpellEffect("gametestaddmarker", GameTestAddMarkerEffect.class); + addSpellEffect("gametestclearmarkers", GameTestClearMarkersEffect.class); addSpellEffect("itemcooldown", ItemCooldownEffect.class); addSpellEffect("itemspray", ItemSprayEffect.class); addSpellEffect("lightning", LightningEffect.class); diff --git a/core/src/main/java/com/nisovin/magicspells/volatilecode/VolatileCodeDisabled.java b/core/src/main/java/com/nisovin/magicspells/volatilecode/VolatileCodeDisabled.java index 6d9954314..89b51496c 100644 --- a/core/src/main/java/com/nisovin/magicspells/volatilecode/VolatileCodeDisabled.java +++ b/core/src/main/java/com/nisovin/magicspells/volatilecode/VolatileCodeDisabled.java @@ -14,7 +14,6 @@ import io.papermc.paper.advancement.AdvancementDisplay.Frame; - public class VolatileCodeDisabled extends VolatileCodeHandle { public VolatileCodeDisabled() { @@ -71,4 +70,14 @@ public void sendStatusUpdate(Player player, double health, int food, float satur } + @Override + public void addGameTestMarker(Player player, Location location, int color, String name, int lifetime) { + + } + + @Override + public void clearGameTestMarkers(Player player) { + + } + } diff --git a/nms/shared/src/main/java/com/nisovin/magicspells/volatilecode/VolatileCodeHandle.java b/nms/shared/src/main/java/com/nisovin/magicspells/volatilecode/VolatileCodeHandle.java index 2efb31556..52cd93245 100644 --- a/nms/shared/src/main/java/com/nisovin/magicspells/volatilecode/VolatileCodeHandle.java +++ b/nms/shared/src/main/java/com/nisovin/magicspells/volatilecode/VolatileCodeHandle.java @@ -49,4 +49,8 @@ public abstract Recipe createSmithingRecipe( public abstract void sendStatusUpdate(Player player, double health, int food, float saturation); + public abstract void addGameTestMarker(Player player, Location location, int color, String name, int lifetime); + + public abstract void clearGameTestMarkers(Player player); + } diff --git a/nms/v1_20_R2/src/main/java/com/nisovin/magicspells/volatilecode/v1_20_R2/VolatileCode1_20_R2.kt b/nms/v1_20_R2/src/main/java/com/nisovin/magicspells/volatilecode/v1_20_R2/VolatileCode1_20_R2.kt index 10e59171a..8b6d73c25 100644 --- a/nms/v1_20_R2/src/main/java/com/nisovin/magicspells/volatilecode/v1_20_R2/VolatileCode1_20_R2.kt +++ b/nms/v1_20_R2/src/main/java/com/nisovin/magicspells/volatilecode/v1_20_R2/VolatileCode1_20_R2.kt @@ -20,6 +20,7 @@ import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack import net.kyori.adventure.text.Component +import io.papermc.paper.util.MCUtil import io.papermc.paper.adventure.PaperAdventure import io.papermc.paper.advancement.AdvancementDisplay @@ -33,6 +34,9 @@ import net.minecraft.world.item.alchemy.PotionUtils import net.minecraft.network.syncher.EntityDataAccessor import net.minecraft.advancements.critereon.ImpossibleTrigger import net.minecraft.world.entity.boss.enderdragon.EnderDragon +import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket +import net.minecraft.network.protocol.common.custom.GameTestAddMarkerDebugPayload +import net.minecraft.network.protocol.common.custom.GameTestClearMarkersDebugPayload import com.nisovin.magicspells.volatilecode.VolatileCodeHandle import com.nisovin.magicspells.volatilecode.VolatileCodeHelper @@ -180,4 +184,14 @@ class VolatileCode1_20_R2(helper: VolatileCodeHelper) : VolatileCodeHandle(helpe (player as CraftPlayer).handle.connection.send(ClientboundSetHealthPacket(health.toFloat(), food, saturation)) } + override fun addGameTestMarker(player: Player, location: Location, color: Int, name: String, lifetime: Int) { + val payload = GameTestAddMarkerDebugPayload(MCUtil.toBlockPosition(location), color, name, lifetime) + (player as CraftPlayer).handle.connection.send(ClientboundCustomPayloadPacket(payload)) + } + + override fun clearGameTestMarkers(player: Player) { + val payload = GameTestClearMarkersDebugPayload() + (player as CraftPlayer).handle.connection.send(ClientboundCustomPayloadPacket(payload)) + } + } diff --git a/nms/v1_20_R3/src/main/java/com/nisovin/magicspells/volatilecode/v1_20_R3/VolatileCode1_20_R3.kt b/nms/v1_20_R3/src/main/java/com/nisovin/magicspells/volatilecode/v1_20_R3/VolatileCode1_20_R3.kt index c4f616f4d..bf6643188 100644 --- a/nms/v1_20_R3/src/main/java/com/nisovin/magicspells/volatilecode/v1_20_R3/VolatileCode1_20_R3.kt +++ b/nms/v1_20_R3/src/main/java/com/nisovin/magicspells/volatilecode/v1_20_R3/VolatileCode1_20_R3.kt @@ -20,6 +20,7 @@ import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack import net.kyori.adventure.text.Component +import io.papermc.paper.util.MCUtil import io.papermc.paper.adventure.PaperAdventure import io.papermc.paper.advancement.AdvancementDisplay @@ -33,6 +34,9 @@ import net.minecraft.world.item.alchemy.PotionUtils import net.minecraft.network.syncher.EntityDataAccessor import net.minecraft.advancements.critereon.ImpossibleTrigger import net.minecraft.world.entity.boss.enderdragon.EnderDragon +import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket +import net.minecraft.network.protocol.common.custom.GameTestAddMarkerDebugPayload +import net.minecraft.network.protocol.common.custom.GameTestClearMarkersDebugPayload import com.nisovin.magicspells.volatilecode.VolatileCodeHandle import com.nisovin.magicspells.volatilecode.VolatileCodeHelper @@ -180,4 +184,14 @@ class VolatileCode1_20_R3(helper: VolatileCodeHelper) : VolatileCodeHandle(helpe (player as CraftPlayer).handle.connection.send(ClientboundSetHealthPacket(health.toFloat(), food, saturation)) } + override fun addGameTestMarker(player: Player, location: Location, color: Int, name: String, lifetime: Int) { + val payload = GameTestAddMarkerDebugPayload(MCUtil.toBlockPosition(location), color, name, lifetime) + (player as CraftPlayer).handle.connection.send(ClientboundCustomPayloadPacket(payload)) + } + + override fun clearGameTestMarkers(player: Player) { + val payload = GameTestClearMarkersDebugPayload() + (player as CraftPlayer).handle.connection.send(ClientboundCustomPayloadPacket(payload)) + } + }