diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 7891eaa..6ea324d 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,34 +5,31 @@ - - - - - - - - - - - - - - - - - + + + - + + - - - + + + + + + + + + + + + + + - - { + "keyToString": { + "Gradle.Build GeyserModelEngine.executor": "Run", + "Gradle.Download Sources.executor": "Run", + "Gradle.GeyserModelEngine [build].executor": "Run", + "Gradle.GeyserModelEngine [jar].executor": "Run", + "Maven.GeyserModelEngine [install...].executor": "Run", + "Maven.GeyserModelEngine [install].executor": "Run", + "ModuleVcsDetector.initialDetectionPerformed": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.git.unshallow": "true", + "git-widget-placeholder": "bettermodel-support-dev", + "kotlin-language-version-configured": "true", + "last_opened_file_path": "D:/Coding/Forks/Minecraft/GeyserModelEngine", + "project.structure.last.edited": "Project", + "project.structure.proportion": "0.0", + "project.structure.side.proportion": "0.2", + "settings.editor.selected.configurable": "reference.settings.project.maven.runner" } -}]]> +} diff --git a/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java b/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java index 3c1b083..7b2f283 100644 --- a/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java +++ b/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java @@ -53,10 +53,9 @@ public class GeyserModelEngine extends JavaPlugin { @Override public void onDisable() { + this.modelManager.removeEntities(); + PacketEvents.getAPI().terminate(); - - this.modelManager.getModelHandler().removeEntities(this); - CommandAPI.onDisable(); } diff --git a/src/main/java/re/imc/geysermodelengine/listener/BetterModelListener.java b/src/main/java/re/imc/geysermodelengine/listener/BetterModelListener.java index d60c5fb..7caaaf9 100644 --- a/src/main/java/re/imc/geysermodelengine/listener/BetterModelListener.java +++ b/src/main/java/re/imc/geysermodelengine/listener/BetterModelListener.java @@ -1,7 +1,9 @@ package re.imc.geysermodelengine.listener; -import kr.toxicity.model.api.event.CreateTrackerEvent; +import kr.toxicity.model.api.event.CreateEntityTrackerEvent; + import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import re.imc.geysermodelengine.GeyserModelEngine; @@ -13,8 +15,8 @@ public class BetterModelListener implements Listener { this.plugin = plugin; } - @EventHandler - public void onModelSpawn(CreateTrackerEvent event) { - plugin.getLogger().info(event.getTracker().name()); + @EventHandler(priority = EventPriority.MONITOR) + public void onModelSpawn(CreateEntityTrackerEvent event) { + plugin.getModelManager().getModelHandler().createModel(event.sourceEntity(), event.getTracker()); } } diff --git a/src/main/java/re/imc/geysermodelengine/listener/ModelEngineListener.java b/src/main/java/re/imc/geysermodelengine/listener/ModelEngineListener.java index 4081231..89abd0e 100644 --- a/src/main/java/re/imc/geysermodelengine/listener/ModelEngineListener.java +++ b/src/main/java/re/imc/geysermodelengine/listener/ModelEngineListener.java @@ -26,7 +26,7 @@ public class ModelEngineListener implements Listener { @EventHandler(priority = EventPriority.MONITOR) public void onAddModel(AddModelEvent event) { if (event.isCancelled()) return; - plugin.getModelManager().getModelHandler().createModel(plugin, event.getTarget(), event.getModel()); + plugin.getModelManager().getModelHandler().createModel(event.getTarget(), event.getModel()); } // Needs Testing diff --git a/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java b/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java index 1a2d009..dfc268b 100644 --- a/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java +++ b/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java @@ -26,12 +26,12 @@ public class ModelListener implements Listener { @EventHandler public void onWorldInit(WorldInitEvent event) { World world = event.getWorld(); - world.getEntities().forEach(entity -> plugin.getModelManager().getModelHandler().processEntities(plugin, entity)); + world.getEntities().forEach(entity -> plugin.getModelManager().getModelHandler().processEntities(entity)); } /* / xSquishyLiam: - / A runDelay make sures the client doesn't see pigs on login due to the client resyncing themselves back to normal + / A runDelay makes sure the client doesn't see pigs on login due to the client resyncing themselves back to normal */ @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/EntityTaskManager.java b/src/main/java/re/imc/geysermodelengine/managers/model/EntityTaskManager.java index 92a5a97..4af61f7 100644 --- a/src/main/java/re/imc/geysermodelengine/managers/model/EntityTaskManager.java +++ b/src/main/java/re/imc/geysermodelengine/managers/model/EntityTaskManager.java @@ -1,9 +1,7 @@ package re.imc.geysermodelengine.managers.model; import com.ticxo.modelengine.api.animation.BlueprintAnimation; -import com.ticxo.modelengine.api.generator.blueprint.BlueprintBone; import com.ticxo.modelengine.api.model.ActiveModel; -import com.ticxo.modelengine.api.model.render.DisplayRenderer; import me.zimzaza4.geyserutils.spigot.api.EntityUtils; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -11,12 +9,12 @@ import org.bukkit.entity.Player; import org.geysermc.floodgate.api.FloodgateApi; import re.imc.geysermodelengine.GeyserModelEngine; import re.imc.geysermodelengine.managers.model.entity.EntityData; -import re.imc.geysermodelengine.managers.model.propertyhandler.BetterModelPropertyHandler; -import re.imc.geysermodelengine.managers.model.propertyhandler.ModelEnginePropertyHandler; -import re.imc.geysermodelengine.managers.model.propertyhandler.PropertyHandler; +import re.imc.geysermodelengine.managers.model.PropertyHandler.BetterModelPropertyHandler; +import re.imc.geysermodelengine.managers.model.PropertyHandler.ModelEnginePropertyHandler; +import re.imc.geysermodelengine.managers.model.PropertyHandler.PropertyHandler; import re.imc.geysermodelengine.managers.model.entity.ModelEngineEntityData; +import re.imc.geysermodelengine.managers.model.taskshandler.TaskHandler; import re.imc.geysermodelengine.packet.entity.PacketEntity; -import re.imc.geysermodelengine.runnables.EntityTaskRunnable; import java.util.*; @@ -30,10 +28,10 @@ public class EntityTaskManager { this.plugin = plugin; if (Bukkit.getPluginManager().getPlugin("ModelEngine") != null) { - this.propertyHandler = new ModelEnginePropertyHandler(); + this.propertyHandler = new ModelEnginePropertyHandler(plugin); plugin.getLogger().info("Using ModelEngine property handler!"); } else if (Bukkit.getPluginManager().getPlugin("BetterModel") != null) { - this.propertyHandler = new BetterModelPropertyHandler(); + this.propertyHandler = new BetterModelPropertyHandler(plugin); plugin.getLogger().info("Using BetterModel property handler!"); } else { plugin.getLogger().severe("No supported model engine found!"); @@ -41,16 +39,6 @@ public class EntityTaskManager { } } - public String unstripName(BlueprintBone bone) { - String name = bone.getName(); - if (bone.getBehaviors().get("head") != null) { - if (!bone.getBehaviors().get("head").isEmpty()) return "hi_" + name; - return "h_" + name; - } - - return name; - } - public void checkViewers(EntityData model, Set viewers) { for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { if (!FloodgateApi.getInstance().isFloodgatePlayer(onlinePlayer.getUniqueId())) continue; @@ -70,13 +58,13 @@ public class EntityTaskManager { } private void sendSpawnPacket(EntityData model, Player onlinePlayer) { - EntityTaskRunnable task = model.getEntityTask(); + TaskHandler task = model.getEntityTask(); boolean firstJoined = !plugin.getModelManager().getPlayerJoinedCache().contains(onlinePlayer.getUniqueId()); if (firstJoined) { - task.sendEntityData((ModelEngineEntityData) model, onlinePlayer, plugin.getConfigManager().getConfig().getInt("join-send-delay") / 50); + task.sendEntityData(model, onlinePlayer, plugin.getConfigManager().getConfig().getInt("join-send-delay") / 50); } else { - task.sendEntityData((ModelEngineEntityData) model, onlinePlayer, 5); + task.sendEntityData(model, onlinePlayer, 5); } } @@ -95,24 +83,13 @@ public class EntityTaskManager { return true; } - public void sendHitBoxToAll(ModelEngineEntityData model) { + public void sendHitBoxToAll(EntityData model) { for (Player viewer : model.getViewers()) { EntityUtils.sendCustomHitBox(viewer, model.getEntity().getEntityId(), 0.01f, 0.01f); } } - public void sendHitBox(ModelEngineEntityData model, Player viewer) { - float w = 0; - - if (model.getActiveModel().isShadowVisible()) { - if (model.getActiveModel().getModelRenderer() instanceof DisplayRenderer displayRenderer) { - // w = displayRenderer.getHitbox().getShadowRadius().get(); - } - } - - EntityUtils.sendCustomHitBox(viewer, model.getEntity().getEntityId(), 0.02f, w); - } - + //TODO move this public boolean hasAnimation(ModelEngineEntityData model, String animation) { ActiveModel activeModel = model.getActiveModel(); BlueprintAnimation animationProperty = activeModel.getBlueprint().getAnimations().get(animation); diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/ModelHandler/BetterModelHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/ModelHandler/BetterModelHandler.java new file mode 100644 index 0000000..f3ce9e1 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/ModelHandler/BetterModelHandler.java @@ -0,0 +1,63 @@ +package re.imc.geysermodelengine.managers.model.ModelHandler; + +import kr.toxicity.model.api.tracker.Tracker; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.listener.BetterModelListener; +import re.imc.geysermodelengine.managers.model.PropertyHandler.PropertyHandler; +import re.imc.geysermodelengine.managers.model.entity.BetterModelEntityData; +import re.imc.geysermodelengine.managers.model.entity.EntityData; +import re.imc.geysermodelengine.managers.model.model.BetterModelModel; +import re.imc.geysermodelengine.managers.model.model.Model; + +import java.util.HashMap; +import java.util.Map; + +public class BetterModelHandler implements ModelHandler { + + private final GeyserModelEngine plugin; + + public BetterModelHandler(GeyserModelEngine plugin) { + this.plugin = plugin; + } + + // Why do you dupe smhhhh + @Override + public void createModel(Object... objects) { + Entity entitySource = (Entity) objects[0]; + Tracker tracker = (Tracker) objects[1]; + + int entityID = entitySource.getEntityId(); + + PropertyHandler propertyHandler = plugin.getEntityTaskManager().getPropertyHandler(); + EntityData entityData = new BetterModelEntityData(plugin, entitySource, tracker); + + Model model = new BetterModelModel(tracker, this, entityData, propertyHandler); + + Map entityDataCache = plugin.getModelManager().getEntitiesCache().computeIfAbsent(entityID, k -> new HashMap<>()); + + for (Map.Entry entry : entityDataCache.entrySet()) { + if (entry.getKey() != model && entry.getKey().getName().equals(tracker.name())) { + return; + } + } + + plugin.getModelManager().getModelEntitiesCache().put(entityID, model); + entityDataCache.put(model, entityData); + } + + @Override + public void processEntities(Entity entity) { +// if (plugin.getModelManager().getEntitiesCache().containsKey(entity.getEntityId())) return; +// +// @NotNull Optional modeledEntity = BetterModel.registry(entity); +// +// modeledEntity.ifPresent(m -> createModel(modeledEntity.get().entity(), m.)); + } + + @Override + public void loadListeners() { + Bukkit.getPluginManager().registerEvents(new BetterModelListener(plugin), plugin); + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/modelhandler/ModelEngineHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/ModelHandler/ModelEngineHandler.java similarity index 66% rename from src/main/java/re/imc/geysermodelengine/managers/model/modelhandler/ModelEngineHandler.java rename to src/main/java/re/imc/geysermodelengine/managers/model/ModelHandler/ModelEngineHandler.java index 28e80a2..6ff5935 100644 --- a/src/main/java/re/imc/geysermodelengine/managers/model/modelhandler/ModelEngineHandler.java +++ b/src/main/java/re/imc/geysermodelengine/managers/model/ModelHandler/ModelEngineHandler.java @@ -1,9 +1,8 @@ -package re.imc.geysermodelengine.managers.model.modelhandler; +package re.imc.geysermodelengine.managers.model.ModelHandler; import com.ticxo.modelengine.api.ModelEngineAPI; import com.ticxo.modelengine.api.model.ActiveModel; import com.ticxo.modelengine.api.model.ModeledEntity; -import kr.toxicity.model.api.data.raw.ModelData; import org.bukkit.Bukkit; import org.bukkit.entity.Entity; import re.imc.geysermodelengine.GeyserModelEngine; @@ -12,7 +11,7 @@ import re.imc.geysermodelengine.managers.model.entity.EntityData; import re.imc.geysermodelengine.managers.model.entity.ModelEngineEntityData; import re.imc.geysermodelengine.managers.model.model.Model; import re.imc.geysermodelengine.managers.model.model.ModelEngineModel; -import re.imc.geysermodelengine.managers.model.propertyhandler.PropertyHandler; +import re.imc.geysermodelengine.managers.model.PropertyHandler.PropertyHandler; import java.util.HashMap; import java.util.Map; @@ -20,10 +19,18 @@ import java.util.Optional; public class ModelEngineHandler implements ModelHandler { + //TODO move driver hashmap here + + private final GeyserModelEngine plugin; + + public ModelEngineHandler(GeyserModelEngine plugin) { + this.plugin = plugin; + } + @Override - public void createModel(GeyserModelEngine plugin, Object modeledEntity, Object activeModel) { - ModeledEntity megEntity = (ModeledEntity) modeledEntity; - ActiveModel megActiveModel = (ActiveModel) activeModel; + public void createModel(Object... objects) { + ModeledEntity megEntity = (ModeledEntity) objects[0]; + ActiveModel megActiveModel = (ActiveModel) objects[1]; int entityID = megEntity.getBase().getEntityId(); @@ -35,7 +42,7 @@ public class ModelEngineHandler implements ModelHandler { Map entityDataCache = plugin.getModelManager().getEntitiesCache().computeIfAbsent(entityID, k -> new HashMap<>()); for (Map.Entry entry : entityDataCache.entrySet()) { - if (entry.getKey() != model && entry.getKey().getName().equals(megActiveModel.getBlueprint().getName())) { + if (entry.getKey() != model && entry.getKey().getName().equals(megActiveModel.getBlueprint().getName())) { return; } } @@ -45,25 +52,18 @@ public class ModelEngineHandler implements ModelHandler { } @Override - public void processEntities(GeyserModelEngine plugin, Entity entity) { + public void processEntities(Entity entity) { if (plugin.getModelManager().getEntitiesCache().containsKey(entity.getEntityId())) return; ModeledEntity modeledEntity = ModelEngineAPI.getModeledEntity(entity); if (modeledEntity == null) return; Optional model = modeledEntity.getModels().values().stream().findFirst(); - model.ifPresent(m -> createModel(plugin, modeledEntity, m)); + model.ifPresent(m -> createModel(modeledEntity, m)); } @Override - public void removeEntities(GeyserModelEngine plugin) { - for (Map entities : plugin.getModelManager().getEntitiesCache().values()) { - entities.forEach((model, modelEntity) -> modelEntity.getEntity().remove()); - } - } - - @Override - public void loadListeners(GeyserModelEngine plugin) { + public void loadListeners() { Bukkit.getPluginManager().registerEvents(new ModelEngineListener(plugin), plugin); } } diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/ModelHandler/ModelHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/ModelHandler/ModelHandler.java new file mode 100644 index 0000000..745054d --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/ModelHandler/ModelHandler.java @@ -0,0 +1,12 @@ +package re.imc.geysermodelengine.managers.model.ModelHandler; + +import org.bukkit.entity.Entity; + +public interface ModelHandler { + + void createModel(Object... objects); + + void processEntities(Entity entity); + + void loadListeners(); +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/ModelManager.java b/src/main/java/re/imc/geysermodelengine/managers/model/ModelManager.java index 5ff745f..ef1de37 100644 --- a/src/main/java/re/imc/geysermodelengine/managers/model/ModelManager.java +++ b/src/main/java/re/imc/geysermodelengine/managers/model/ModelManager.java @@ -7,9 +7,9 @@ import org.bukkit.Bukkit; import re.imc.geysermodelengine.GeyserModelEngine; import re.imc.geysermodelengine.managers.model.entity.EntityData; import re.imc.geysermodelengine.managers.model.model.Model; -import re.imc.geysermodelengine.managers.model.modelhandler.BetterModelHandler; -import re.imc.geysermodelengine.managers.model.modelhandler.ModelEngineHandler; -import re.imc.geysermodelengine.managers.model.modelhandler.ModelHandler; +import re.imc.geysermodelengine.managers.model.ModelHandler.BetterModelHandler; +import re.imc.geysermodelengine.managers.model.ModelHandler.ModelEngineHandler; +import re.imc.geysermodelengine.managers.model.ModelHandler.ModelHandler; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -32,10 +32,10 @@ public class ModelManager { this.plugin = plugin; if (Bukkit.getPluginManager().getPlugin("ModelEngine") != null) { - this.modelHandler = new ModelEngineHandler(); + this.modelHandler = new ModelEngineHandler(plugin); plugin.getLogger().info("Using ModelEngine handler!"); } else if (Bukkit.getPluginManager().getPlugin("BetterModel") != null) { - this.modelHandler = new BetterModelHandler(); + this.modelHandler = new BetterModelHandler(plugin); plugin.getLogger().info("Using BetterModel handler!"); } else { plugin.getLogger().severe("No supported model engine found!"); @@ -43,7 +43,13 @@ public class ModelManager { return; } - modelHandler.loadListeners(plugin); + modelHandler.loadListeners(); + } + + public void removeEntities() { + for (Map entities : entitiesCache.values()) { + entities.forEach((model, modelEntity) -> modelEntity.getEntity().remove()); + } } public ModelHandler getModelHandler() { diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/PropertyHandler/BetterModelPropertyHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/PropertyHandler/BetterModelPropertyHandler.java new file mode 100644 index 0000000..add973a --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/PropertyHandler/BetterModelPropertyHandler.java @@ -0,0 +1,155 @@ +package re.imc.geysermodelengine.managers.model.PropertyHandler; + +import kr.toxicity.model.api.animation.AnimationIterator; +import kr.toxicity.model.api.bone.RenderedBone; +import kr.toxicity.model.api.data.blueprint.BlueprintAnimation; +import kr.toxicity.model.api.data.renderer.RenderPipeline; +import kr.toxicity.model.api.nms.ModelDisplay; +import me.zimzaza4.geyserutils.spigot.api.EntityUtils; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.model.entity.BetterModelEntityData; +import re.imc.geysermodelengine.managers.model.entity.EntityData; +import re.imc.geysermodelengine.util.BooleanPacker; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class BetterModelPropertyHandler implements PropertyHandler { + + private final GeyserModelEngine plugin; + + public BetterModelPropertyHandler(GeyserModelEngine plugin) { + this.plugin = plugin; + } + + // Other question is how am I meant to get the scale?? + @Override + public void sendScale(EntityData entityData, Collection players, float lastScale, boolean firstSend) { + + } + + // Now real question how do I get the tint? + @Override + public void sendColor(EntityData entityData, Collection players, Color lastColor, boolean firstSend) { + + } + + @Override + public void sendHitBox(EntityData entityData, Player player) { + BetterModelEntityData betterModelEntityData = (BetterModelEntityData) entityData; + + float w = 0; + + EntityUtils.sendCustomHitBox(player, betterModelEntityData.getEntity().getEntityId(), 0.02f, w); + } + + @Override + public void updateEntityProperties(EntityData entityData, Collection players, boolean firstSend, String... forceAnims) { + BetterModelEntityData model = (BetterModelEntityData) entityData; + + int entity = model.getEntity().getEntityId(); + Set forceAnimSet = Set.of(forceAnims); + + Map boneUpdates = new HashMap<>(); + Map animUpdates = new HashMap<>(); + Set anims = new HashSet<>(); + + model.getTracker().bones().forEach(bone -> processBone(model, bone, boneUpdates)); + + RenderPipeline handler = model.getTracker().getPipeline(); + + for (RenderedBone renderedBone : handler.bones()) { + if (model.getTracker().bone(renderedBone.name()).runningAnimation() != null) { + BlueprintAnimation anim = model.getTracker().renderer().animationMap().get(renderedBone.runningAnimation().name()); + + anims.add(renderedBone.runningAnimation().name()); + if (anim.override() && anim.loop() == AnimationIterator.Type.PLAY_ONCE) { + break; + } + } + } + + for (String id : handler.getParent().animations()) { + if (anims.contains(id)) { + animUpdates.put(id, true); + } else { + animUpdates.put(id, false); + } + } + + Set lastPlayed = new HashSet<>(model.getEntityTask().getLastPlayedAnim().asMap().keySet()); + + for (Map.Entry anim : animUpdates.entrySet()) { + if (anim.getValue()) { + model.getEntityTask().getLastPlayedAnim().put(anim.getKey(), true); + } + } + + for (String anim : lastPlayed) animUpdates.put(anim, true); + + if (boneUpdates.isEmpty() && animUpdates.isEmpty()) return; + + Map intUpdates = new HashMap<>(); + int i = 0; + + for (Integer integer : BooleanPacker.mapBooleansToInts(boneUpdates)) { + intUpdates.put(plugin.getConfigManager().getConfig().getString("namespace") + ":bone" + i, integer); + i++; + } + + i = 0; + for (Integer integer : BooleanPacker.mapBooleansToInts(animUpdates)) { + intUpdates.put(plugin.getConfigManager().getConfig().getString("namespace") + ":anim" + i, integer); + i++; + } + + if (!firstSend) { + if (intUpdates.equals(model.getEntityTask().getLastIntSet())) { + return; + } else { + model.getEntityTask().getLastIntSet().clear(); + model.getEntityTask().getLastIntSet().putAll(intUpdates); + } + } + + if (plugin.getConfigManager().getConfig().getBoolean("debug")) plugin.getLogger().info(animUpdates.toString()); + + List list = new ArrayList<>(boneUpdates.keySet()); + Collections.sort(list); + + for (Player player : players) { + EntityUtils.sendIntProperties(player, entity, intUpdates); + } + } + + public String unstripName(RenderedBone bone) { + @NotNull String name = bone.name().rawName(); + + if (name.equals("head")) { + if (!bone.getChildren().isEmpty()) return "hi_" + name; + return "h_" + name; + } + + return name; + } + + private void processBone(BetterModelEntityData entityData, RenderedBone bone, Map map) { + String name = unstripName(bone).toLowerCase(); + if (name.equals("hitbox") || name.equals("shadow") || name.equals("mount") || name.startsWith("p_") || name.startsWith("b_") || name.startsWith("ob_")) return; + + for (RenderedBone renderedBone : bone.getChildren().values()) { + processBone(entityData, renderedBone, map); + } + + RenderedBone activeBone = entityData.getTracker().bone(bone.name()); + + ModelDisplay modelDisplay = activeBone.getDisplay(); + if (modelDisplay == null) return; + boolean visible = activeBone.getDisplay().invisible(); + + map.put(name, visible); + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/PropertyHandler/ModelEnginePropertyHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/PropertyHandler/ModelEnginePropertyHandler.java new file mode 100644 index 0000000..0365f91 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/PropertyHandler/ModelEnginePropertyHandler.java @@ -0,0 +1,196 @@ +package re.imc.geysermodelengine.managers.model.PropertyHandler; + +import com.ticxo.modelengine.api.animation.BlueprintAnimation; +import com.ticxo.modelengine.api.animation.handler.AnimationHandler; +import com.ticxo.modelengine.api.generator.blueprint.BlueprintBone; +import com.ticxo.modelengine.api.model.ActiveModel; +import com.ticxo.modelengine.api.model.bone.ModelBone; +import com.ticxo.modelengine.api.model.render.DisplayRenderer; +import me.zimzaza4.geyserutils.spigot.api.EntityUtils; +import org.bukkit.entity.Player; +import org.joml.Vector3fc; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.model.entity.EntityData; +import re.imc.geysermodelengine.managers.model.entity.ModelEngineEntityData; +import re.imc.geysermodelengine.util.BooleanPacker; + +import java.awt.*; +import java.lang.reflect.Method; +import java.util.*; +import java.util.List; + +public class ModelEnginePropertyHandler implements PropertyHandler { + + private final GeyserModelEngine plugin; + + private final Method scaleMethod; + + public ModelEnginePropertyHandler(GeyserModelEngine plugin) { + this.plugin = plugin; + + try { + this.scaleMethod = ActiveModel.class.getMethod("getScale"); + } catch (NoSuchMethodException err) { + throw new RuntimeException(err); + } + } + + @Override + public void sendScale(EntityData modelData, Collection players, float lastScale, boolean firstSend) { + try { + if (players.isEmpty()) return; + + ModelEngineEntityData modelEngineEntityData = (ModelEngineEntityData) modelData; + + Vector3fc scale = (Vector3fc) scaleMethod.invoke(modelEngineEntityData.getActiveModel()); + + float average = (scale.x() + scale.y() + scale.z()) / 3; + + if (!firstSend) { + if (average == lastScale) return; + } + + for (Player player : players) { + EntityUtils.sendCustomScale(player, modelEngineEntityData.getEntity().getEntityId(), average); + } + } catch (Throwable ignored) {} + } + + @Override + public void sendColor(EntityData entityData, Collection players, Color lastColor, boolean firstSend) { + if (players.isEmpty()) return; + + ModelEngineEntityData modelEngineEntityData = (ModelEngineEntityData) entityData; + + Color color = new Color(modelEngineEntityData.getActiveModel().getDefaultTint().asARGB()); + if (modelEngineEntityData.getActiveModel().isMarkedHurt()) color = new Color(modelEngineEntityData.getActiveModel().getDamageTint().asARGB()); + + if (firstSend) { + if (color.equals(lastColor)) return; + } + + for (Player player : players) { + EntityUtils.sendCustomColor(player, modelEngineEntityData.getEntity().getEntityId(), color); + } + } + + @Override + public void sendHitBox(EntityData entityData, Player player) { + ModelEngineEntityData modelEngineEntityData = (ModelEngineEntityData) entityData; + + float w = 0; + + if (modelEngineEntityData.getActiveModel().isShadowVisible()) { + if (modelEngineEntityData.getActiveModel().getModelRenderer() instanceof DisplayRenderer displayRenderer) { + // w = displayRenderer.getHitbox().getShadowRadius().get(); + } + } + + EntityUtils.sendCustomHitBox(player, modelEngineEntityData.getEntity().getEntityId(), 0.02f, w); + } + + @Override + public void updateEntityProperties(EntityData entityData, Collection players, boolean firstSend, String... forceAnims) { + ModelEngineEntityData model = (ModelEngineEntityData) entityData; + + int entity = model.getEntity().getEntityId(); + Set forceAnimSet = Set.of(forceAnims); + + Map boneUpdates = new HashMap<>(); + Map animUpdates = new HashMap<>(); + Set anims = new HashSet<>(); + + model.getActiveModel().getBlueprint().getBones().forEach((s, bone) -> processBone(model, bone, boneUpdates)); + + AnimationHandler handler = model.getActiveModel().getAnimationHandler(); + Set priority = model.getActiveModel().getBlueprint().getAnimationDescendingPriority(); + for (String animId : priority) { + if (handler.isPlayingAnimation(animId)) { + BlueprintAnimation anim = model.getActiveModel().getBlueprint().getAnimations().get(animId); + + anims.add(animId); + if (anim.isOverride() && anim.getLoopMode() == BlueprintAnimation.LoopMode.ONCE) { + break; + } + } + } + + for (String id : priority) { + if (anims.contains(id)) { + animUpdates.put(id, true); + } else { + animUpdates.put(id, false); + } + } + + Set lastPlayed = new HashSet<>(model.getEntityTask().getLastPlayedAnim().asMap().keySet()); + + for (Map.Entry anim : animUpdates.entrySet()) { + if (anim.getValue()) { + model.getEntityTask().getLastPlayedAnim().put(anim.getKey(), true); + } + } + + for (String anim : lastPlayed) animUpdates.put(anim, true); + + if (boneUpdates.isEmpty() && animUpdates.isEmpty()) return; + + Map intUpdates = new HashMap<>(); + int i = 0; + + for (Integer integer : BooleanPacker.mapBooleansToInts(boneUpdates)) { + intUpdates.put(plugin.getConfigManager().getConfig().getString("namespace") + ":bone" + i, integer); + i++; + } + + i = 0; + for (Integer integer : BooleanPacker.mapBooleansToInts(animUpdates)) { + intUpdates.put(plugin.getConfigManager().getConfig().getString("namespace") + ":anim" + i, integer); + i++; + } + + if (!firstSend) { + if (intUpdates.equals(model.getEntityTask().getLastIntSet())) { + return; + } else { + model.getEntityTask().getLastIntSet().clear(); + model.getEntityTask().getLastIntSet().putAll(intUpdates); + } + } + + if (plugin.getConfigManager().getConfig().getBoolean("debug")) plugin.getLogger().info(animUpdates.toString()); + + List list = new ArrayList<>(boneUpdates.keySet()); + Collections.sort(list); + + for (Player player : players) { + EntityUtils.sendIntProperties(player, entity, intUpdates); + } + } + + public String unstripName(BlueprintBone bone) { + String name = bone.getName(); + if (bone.getBehaviors().get("head") != null) { + if (!bone.getBehaviors().get("head").isEmpty()) return "hi_" + name; + return "h_" + name; + } + + return name; + } + + private void processBone(ModelEngineEntityData model, BlueprintBone bone, Map map) { + String name = unstripName(bone).toLowerCase(); + if (name.equals("hitbox") || name.equals("shadow") || name.equals("mount") || name.startsWith("p_") || name.startsWith("b_") || name.startsWith("ob_")) return; + + for (BlueprintBone blueprintBone : bone.getChildren().values()) { + processBone(model, blueprintBone, map); + } + + ModelBone activeBone = model.getActiveModel().getBones().get(bone.getName()); + + boolean visible = false; + if (activeBone != null) visible = activeBone.isVisible(); + + map.put(name, visible); + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/PropertyHandler/PropertyHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/PropertyHandler/PropertyHandler.java new file mode 100644 index 0000000..ab2ab71 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/PropertyHandler/PropertyHandler.java @@ -0,0 +1,16 @@ +package re.imc.geysermodelengine.managers.model.PropertyHandler; + +import org.bukkit.entity.Player; +import re.imc.geysermodelengine.managers.model.entity.EntityData; + +import java.awt.*; +import java.util.Collection; + +public interface PropertyHandler { + + void sendScale(EntityData entityData, Collection players, float lastScale, boolean firstSend); + void sendColor(EntityData entityData, Collection players, Color lastColor, boolean firstSend); + void sendHitBox(EntityData entityData, Player player); + + void updateEntityProperties(EntityData entityData, Collection players, boolean firstSend, String... forceAnims); +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/entity/BetterModelEntityData.java b/src/main/java/re/imc/geysermodelengine/managers/model/entity/BetterModelEntityData.java index 192dd3d..75a891c 100644 --- a/src/main/java/re/imc/geysermodelengine/managers/model/entity/BetterModelEntityData.java +++ b/src/main/java/re/imc/geysermodelengine/managers/model/entity/BetterModelEntityData.java @@ -1,4 +1,69 @@ package re.imc.geysermodelengine.managers.model.entity; -public class BetterModelEntityData { +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.google.common.collect.Sets; +import kr.toxicity.model.api.tracker.Tracker; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.model.taskshandler.BetterModelTaskHandler; +import re.imc.geysermodelengine.packet.entity.PacketEntity; + +import java.util.Set; + +public class BetterModelEntityData implements EntityData { + + private final GeyserModelEngine plugin; + + private final PacketEntity entity; + private final Set viewers = Sets.newConcurrentHashSet(); + + private final Entity entitySource; + private final Tracker tracker; + + private BetterModelTaskHandler entityTask; + + public BetterModelEntityData(GeyserModelEngine plugin, Entity entitySource, Tracker tracker) { + this.plugin = plugin; + + this.entitySource = entitySource; + this.tracker = tracker; + this.entity = new PacketEntity(EntityTypes.PIG, viewers, entitySource.getLocation()); + + runEntityTask(); + } + + @Override + public void teleportToModel() { + Location location = entitySource.getLocation(); + entity.teleport(location); + } + + public void runEntityTask() { + entityTask = new BetterModelTaskHandler(plugin, this); + } + + @Override + public PacketEntity getEntity() { + return entity; + } + + @Override + public Set getViewers() { + return viewers; + } + + @Override + public BetterModelTaskHandler getEntityTask() { + return entityTask; + } + + public Entity getEntitySource() { + return entitySource; + } + + public Tracker getTracker() { + return tracker; + } } diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/entity/EntityData.java b/src/main/java/re/imc/geysermodelengine/managers/model/entity/EntityData.java index 22f70ef..9fb8105 100644 --- a/src/main/java/re/imc/geysermodelengine/managers/model/entity/EntityData.java +++ b/src/main/java/re/imc/geysermodelengine/managers/model/entity/EntityData.java @@ -1,20 +1,17 @@ package re.imc.geysermodelengine.managers.model.entity; import org.bukkit.entity.Player; -import re.imc.geysermodelengine.managers.model.model.Model; +import re.imc.geysermodelengine.managers.model.taskshandler.TaskHandler; import re.imc.geysermodelengine.packet.entity.PacketEntity; -import re.imc.geysermodelengine.runnables.EntityTaskRunnable; import java.util.Set; public interface EntityData { + void teleportToModel(); + PacketEntity getEntity(); Set getViewers(); - void teleportToModel(); - - void remove(); - - EntityTaskRunnable getEntityTask(); + TaskHandler getEntityTask(); } diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/entity/ModelEngineEntityData.java b/src/main/java/re/imc/geysermodelengine/managers/model/entity/ModelEngineEntityData.java index 5f2499d..4454775 100644 --- a/src/main/java/re/imc/geysermodelengine/managers/model/entity/ModelEngineEntityData.java +++ b/src/main/java/re/imc/geysermodelengine/managers/model/entity/ModelEngineEntityData.java @@ -7,9 +7,8 @@ import com.ticxo.modelengine.api.model.ModeledEntity; import org.bukkit.Location; import org.bukkit.entity.Player; import re.imc.geysermodelengine.GeyserModelEngine; -import re.imc.geysermodelengine.managers.model.model.Model; +import re.imc.geysermodelengine.managers.model.taskshandler.ModelEngineTaskHandler; import re.imc.geysermodelengine.packet.entity.PacketEntity; -import re.imc.geysermodelengine.runnables.EntityTaskRunnable; import java.util.Set; @@ -18,14 +17,12 @@ public class ModelEngineEntityData implements EntityData { private final GeyserModelEngine plugin; private final PacketEntity entity; - private final Set viewers = Sets.newConcurrentHashSet(); private final ModeledEntity modeledEntity; - private final ActiveModel activeModel; - private EntityTaskRunnable entityTask; + private ModelEngineTaskHandler entityTask; public ModelEngineEntityData(GeyserModelEngine plugin, ModeledEntity modeledEntity, ActiveModel activeModel) { this.plugin = plugin; @@ -44,7 +41,7 @@ public class ModelEngineEntityData implements EntityData { } public void runEntityTask() { - entityTask = new EntityTaskRunnable(plugin, this); + entityTask = new ModelEngineTaskHandler(plugin, this); } @Override @@ -58,12 +55,7 @@ public class ModelEngineEntityData implements EntityData { } @Override - public void remove() { - - } - - @Override - public EntityTaskRunnable getEntityTask() { + public ModelEngineTaskHandler getEntityTask() { return entityTask; } diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/model/BetterModelModel.java b/src/main/java/re/imc/geysermodelengine/managers/model/model/BetterModelModel.java index 51bc102..305aca4 100644 --- a/src/main/java/re/imc/geysermodelengine/managers/model/model/BetterModelModel.java +++ b/src/main/java/re/imc/geysermodelengine/managers/model/model/BetterModelModel.java @@ -1,28 +1,41 @@ package re.imc.geysermodelengine.managers.model.model; +import kr.toxicity.model.api.tracker.Tracker; import re.imc.geysermodelengine.managers.model.entity.EntityData; -import re.imc.geysermodelengine.managers.model.modelhandler.ModelHandler; -import re.imc.geysermodelengine.managers.model.propertyhandler.PropertyHandler; +import re.imc.geysermodelengine.managers.model.ModelHandler.ModelHandler; +import re.imc.geysermodelengine.managers.model.PropertyHandler.PropertyHandler; public class BetterModelModel implements Model { + private final Tracker tracker; + private final ModelHandler modelHandler; + private final EntityData entityData; + private final PropertyHandler propertyHandler; + + public BetterModelModel(Tracker tracker, ModelHandler modelHandler, EntityData entityData, PropertyHandler propertyHandler) { + this.tracker = tracker; + this.modelHandler = modelHandler; + this.entityData = entityData; + this.propertyHandler = propertyHandler; + } + @Override public String getName() { - return ""; + return tracker.name(); } @Override public ModelHandler getModelHandler() { - return null; + return modelHandler; } @Override public EntityData getEntityData() { - return null; + return entityData; } @Override public PropertyHandler getPropertyHandler() { - return null; + return propertyHandler; } } diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/model/Model.java b/src/main/java/re/imc/geysermodelengine/managers/model/model/Model.java index 6752878..9815727 100644 --- a/src/main/java/re/imc/geysermodelengine/managers/model/model/Model.java +++ b/src/main/java/re/imc/geysermodelengine/managers/model/model/Model.java @@ -1,14 +1,16 @@ package re.imc.geysermodelengine.managers.model.model; import re.imc.geysermodelengine.managers.model.entity.EntityData; -import re.imc.geysermodelengine.managers.model.modelhandler.ModelHandler; -import re.imc.geysermodelengine.managers.model.propertyhandler.PropertyHandler; +import re.imc.geysermodelengine.managers.model.ModelHandler.ModelHandler; +import re.imc.geysermodelengine.managers.model.PropertyHandler.PropertyHandler; public interface Model { String getName(); ModelHandler getModelHandler(); + EntityData getEntityData(); + PropertyHandler getPropertyHandler(); } diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/model/ModelEngineModel.java b/src/main/java/re/imc/geysermodelengine/managers/model/model/ModelEngineModel.java index edf32ee..97fad15 100644 --- a/src/main/java/re/imc/geysermodelengine/managers/model/model/ModelEngineModel.java +++ b/src/main/java/re/imc/geysermodelengine/managers/model/model/ModelEngineModel.java @@ -2,8 +2,8 @@ package re.imc.geysermodelengine.managers.model.model; import com.ticxo.modelengine.api.model.ActiveModel; import re.imc.geysermodelengine.managers.model.entity.EntityData; -import re.imc.geysermodelengine.managers.model.modelhandler.ModelHandler; -import re.imc.geysermodelengine.managers.model.propertyhandler.PropertyHandler; +import re.imc.geysermodelengine.managers.model.ModelHandler.ModelHandler; +import re.imc.geysermodelengine.managers.model.PropertyHandler.PropertyHandler; public class ModelEngineModel implements Model { diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/modelhandler/BetterModelHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/modelhandler/BetterModelHandler.java deleted file mode 100644 index d4b8f32..0000000 --- a/src/main/java/re/imc/geysermodelengine/managers/model/modelhandler/BetterModelHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package re.imc.geysermodelengine.managers.model.modelhandler; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Entity; -import re.imc.geysermodelengine.GeyserModelEngine; -import re.imc.geysermodelengine.listener.BetterModelListener; - -public class BetterModelHandler implements ModelHandler { - - @Override - public void createModel(GeyserModelEngine plugin, Object modeledEntity, Object activeModel) { - - } - - @Override - public void processEntities(GeyserModelEngine plugin, Entity entity) { - - } - - @Override - public void removeEntities(GeyserModelEngine plugin) { - - } - - @Override - public void loadListeners(GeyserModelEngine plugin) { - Bukkit.getPluginManager().registerEvents(new BetterModelListener(plugin), plugin); - } -} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/modelhandler/ModelHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/modelhandler/ModelHandler.java deleted file mode 100644 index 0c4a2ae..0000000 --- a/src/main/java/re/imc/geysermodelengine/managers/model/modelhandler/ModelHandler.java +++ /dev/null @@ -1,16 +0,0 @@ -package re.imc.geysermodelengine.managers.model.modelhandler; - -import org.bukkit.entity.Entity; -import re.imc.geysermodelengine.GeyserModelEngine; - -public interface ModelHandler { - - // Might do a hashmap way tbf - void createModel(GeyserModelEngine plugin, Object modeledEntity, Object activeModel); - - void processEntities(GeyserModelEngine plugin, Entity entity); - - void removeEntities(GeyserModelEngine plugin); - - void loadListeners(GeyserModelEngine plugin); -} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/propertyhandler/BetterModelPropertyHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/propertyhandler/BetterModelPropertyHandler.java deleted file mode 100644 index 11389ef..0000000 --- a/src/main/java/re/imc/geysermodelengine/managers/model/propertyhandler/BetterModelPropertyHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package re.imc.geysermodelengine.managers.model.propertyhandler; - -import org.bukkit.entity.Player; -import re.imc.geysermodelengine.managers.model.entity.EntityData; - -import java.awt.*; -import java.util.Collection; - -public class BetterModelPropertyHandler implements PropertyHandler { - - @Override - public void sendScale(EntityData modelData, Collection players, float lastScale, boolean firstSend) { - - } - - @Override - public void sendColor(EntityData modelData, Collection players, Color lastColor, boolean firstSend) { - - } - - @Override - public void sendHitBox(EntityData modelData, Player player) { - - } -} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/propertyhandler/ModelEnginePropertyHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/propertyhandler/ModelEnginePropertyHandler.java deleted file mode 100644 index c9dc034..0000000 --- a/src/main/java/re/imc/geysermodelengine/managers/model/propertyhandler/ModelEnginePropertyHandler.java +++ /dev/null @@ -1,71 +0,0 @@ -package re.imc.geysermodelengine.managers.model.propertyhandler; - -import com.ticxo.modelengine.api.model.ActiveModel; -import me.zimzaza4.geyserutils.spigot.api.EntityUtils; -import org.bukkit.entity.Player; -import org.joml.Vector3fc; -import re.imc.geysermodelengine.managers.model.entity.EntityData; -import re.imc.geysermodelengine.managers.model.entity.ModelEngineEntityData; - -import java.awt.*; -import java.lang.reflect.Method; -import java.util.Collection; - -public class ModelEnginePropertyHandler implements PropertyHandler { - - private final Method scaleMethod; - - public ModelEnginePropertyHandler() { - try { - this.scaleMethod = ActiveModel.class.getMethod("getScale"); - } catch (NoSuchMethodException err) { - throw new RuntimeException(err); - } - } - - @Override - public void sendScale(EntityData modelData, Collection players, float lastScale, boolean firstSend) { - try { - if (players.isEmpty()) return; - - ModelEngineEntityData modelEngineEntityData = (ModelEngineEntityData) modelData; - - Vector3fc scale = (Vector3fc) scaleMethod.invoke(modelEngineEntityData.getActiveModel()); - - float average = (scale.x() + scale.y() + scale.z()) / 3; - - if (!firstSend) { - if (average == lastScale) return; - } - - for (Player player : players) { - EntityUtils.sendCustomScale(player, modelEngineEntityData.getEntity().getEntityId(), average); - } - } catch (Throwable ignored) {} - } - - @Override - public void sendColor(EntityData modelData, Collection players, Color lastColor, boolean firstSend) { - if (players.isEmpty()) return; - - ModelEngineEntityData modelEngineEntityData = (ModelEngineEntityData) modelData; - - Color color = new Color(modelEngineEntityData.getActiveModel().getDefaultTint().asARGB()); - if (modelEngineEntityData.getActiveModel().isMarkedHurt()) color = new Color(modelEngineEntityData.getActiveModel().getDamageTint().asARGB()); - - if (firstSend) { - if (color.equals(lastColor)) return; - } - - for (Player player : players) { - EntityUtils.sendCustomColor(player, modelEngineEntityData.getEntity().getEntityId(), color); - } - } - - @Override - public void sendHitBox(EntityData modelData, Player player) { - for (Player viewer : modelData.getViewers()) { - EntityUtils.sendCustomHitBox(viewer, modelData.getEntity().getEntityId(), 0.01f, 0.01f); - } - } -} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/propertyhandler/PropertyHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/propertyhandler/PropertyHandler.java deleted file mode 100644 index 57248cc..0000000 --- a/src/main/java/re/imc/geysermodelengine/managers/model/propertyhandler/PropertyHandler.java +++ /dev/null @@ -1,16 +0,0 @@ -package re.imc.geysermodelengine.managers.model.propertyhandler; - -import org.bukkit.entity.Player; -import re.imc.geysermodelengine.managers.model.entity.EntityData; - -import java.awt.*; -import java.util.Collection; - -public interface PropertyHandler { - - void sendScale(EntityData modelData, Collection players, float lastScale, boolean firstSend); - void sendColor(EntityData modelData, Collection players, Color lastColor, boolean firstSend); - void sendHitBox(EntityData modelData, Player player); - - -} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/taskshandler/BetterModelTaskHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/taskshandler/BetterModelTaskHandler.java new file mode 100644 index 0000000..ae57efc --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/taskshandler/BetterModelTaskHandler.java @@ -0,0 +1,171 @@ +package re.imc.geysermodelengine.managers.model.taskshandler; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import kr.toxicity.model.api.tracker.Tracker; +import me.zimzaza4.geyserutils.spigot.api.EntityUtils; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.model.entity.BetterModelEntityData; +import re.imc.geysermodelengine.managers.model.entity.EntityData; +import re.imc.geysermodelengine.packet.entity.PacketEntity; + +import java.awt.*; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class BetterModelTaskHandler implements TaskHandler { + + private final GeyserModelEngine plugin; + + private final BetterModelEntityData entityData; + + private int tick = 0; + private int syncTick = 0; + + private float lastScale = -1.0f; + private Color lastColor = null; + + private boolean removed = false; + + private final ConcurrentHashMap lastIntSet = new ConcurrentHashMap<>(); + private final Cache lastPlayedAnim = CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MILLISECONDS).build(); + + private ScheduledFuture scheduledFuture; + + public BetterModelTaskHandler(GeyserModelEngine plugin, BetterModelEntityData entityData) { + this.plugin = plugin; + this.entityData = entityData; + + plugin.getEntityTaskManager().sendHitBoxToAll(entityData); + scheduledFuture = plugin.getSchedulerPool().scheduleAtFixedRate(this::runAsync, 0, 20, TimeUnit.MILLISECONDS); + } + + @Override + public void runAsync() { + plugin.getEntityTaskManager().checkViewers(entityData, entityData.getViewers()); + + PacketEntity entity = entityData.getEntity(); + if (entity.isDead()) return; + + Set viewers = entityData.getViewers(); + Entity entitySource = entityData.getEntitySource(); + Tracker tracker = entityData.getTracker(); + + entityData.teleportToModel(); + + + if (entitySource.isDead() || tracker.forRemoval()) { + removed = true; + entity.remove(); + + plugin.getModelManager().getEntitiesCache().remove(entitySource.getEntityId()); + plugin.getModelManager().getModelEntitiesCache().remove(entitySource.getEntityId()); + + cancel(); + return; + } + + if (tick % 5 == 0) { + if (tick % 40 == 0) { + for (Player viewer : Set.copyOf(viewers)) { + if (!plugin.getEntityTaskManager().canSee(viewer, entityData.getEntity())) { + viewers.remove(viewer); + } + } + } + } + + tick++; + if (tick > 400) { + tick = 0; + plugin.getEntityTaskManager().sendHitBoxToAll(entityData); + } + + if (viewers.isEmpty()) return; + + plugin.getEntityTaskManager().getPropertyHandler().sendScale(entityData, viewers, lastScale, false); + plugin.getEntityTaskManager().getPropertyHandler().sendColor(entityData, viewers, lastColor, false); + } + + @Override + public void sendEntityData(EntityData entityData, Player player, int delay) { + BetterModelEntityData betterModelEntityData = (BetterModelEntityData) entityData; + + EntityUtils.setCustomEntity(player, betterModelEntityData.getEntity().getEntityId(), plugin.getConfigManager().getConfig().getString("namespace") + ":" + betterModelEntityData.getTracker().name().toLowerCase()); + + plugin.getSchedulerPool().schedule(() -> { + entityData.getEntity().sendSpawnPacket(Collections.singletonList(player)); + + plugin.getSchedulerPool().schedule(() -> { + plugin.getEntityTaskManager().getPropertyHandler().sendHitBox(entityData, player); + + plugin.getEntityTaskManager().getPropertyHandler().sendScale(entityData, Collections.singleton(player), lastScale, true); + plugin.getEntityTaskManager().getPropertyHandler().sendColor(entityData, Collections.singleton(player), lastColor, true); + + plugin.getEntityTaskManager().getPropertyHandler().updateEntityProperties(entityData, Collections.singleton(player), true); + }, 500, TimeUnit.MILLISECONDS); + }, delay * 50L, TimeUnit.MILLISECONDS); + } + + @Override + public void cancel() { + scheduledFuture.cancel(true); + } + + public void setTick(int tick) { + this.tick = tick; + } + + public void setSyncTick(int syncTick) { + this.syncTick = syncTick; + } + + public void setRemoved(boolean removed) { + this.removed = removed; + } + + public void setLastScale(float lastScale) { + this.lastScale = lastScale; + } + + public int getTick() { + return tick; + } + + public int getSyncTick() { + return syncTick; + } + + public void setLastColor(Color lastColor) { + this.lastColor = lastColor; + } + + public float getLastScale() { + return lastScale; + } + + public Color getLastColor() { + return lastColor; + } + + public boolean isRemoved() { + return removed; + } + + public ConcurrentHashMap getLastIntSet() { + return lastIntSet; + } + + public Cache getLastPlayedAnim() { + return lastPlayedAnim; + } + + public ScheduledFuture getScheduledFuture() { + return scheduledFuture; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/taskshandler/ModelEngineTaskHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/taskshandler/ModelEngineTaskHandler.java new file mode 100644 index 0000000..282040b --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/taskshandler/ModelEngineTaskHandler.java @@ -0,0 +1,170 @@ +package re.imc.geysermodelengine.managers.model.taskshandler; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.ticxo.modelengine.api.model.ActiveModel; +import com.ticxo.modelengine.api.model.ModeledEntity; +import me.zimzaza4.geyserutils.spigot.api.EntityUtils; +import org.bukkit.entity.Player; +import re.imc.geysermodelengine.GeyserModelEngine; +import re.imc.geysermodelengine.managers.model.entity.EntityData; +import re.imc.geysermodelengine.managers.model.entity.ModelEngineEntityData; +import re.imc.geysermodelengine.packet.entity.PacketEntity; + +import java.awt.*; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class ModelEngineTaskHandler implements TaskHandler { + + private final GeyserModelEngine plugin; + + private final ModelEngineEntityData entityData; + + private int tick = 0; + private int syncTick = 0; + + private float lastScale = -1.0f; + private Color lastColor = null; + + private boolean removed = false; + + private final ConcurrentHashMap lastIntSet = new ConcurrentHashMap<>(); + private final Cache lastPlayedAnim = CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MILLISECONDS).build(); + + private ScheduledFuture scheduledFuture; + + public ModelEngineTaskHandler(GeyserModelEngine plugin, ModelEngineEntityData entityData) { + this.plugin = plugin; + this.entityData = entityData; + + plugin.getEntityTaskManager().sendHitBoxToAll(entityData); + scheduledFuture = plugin.getSchedulerPool().scheduleAtFixedRate(this::runAsync, 0, 20, TimeUnit.MILLISECONDS); + } + + @Override + public void runAsync() { + plugin.getEntityTaskManager().checkViewers(entityData, entityData.getViewers()); + + PacketEntity entity = entityData.getEntity(); + if (entity.isDead()) return; + + entityData.teleportToModel(); + + Set viewers = entityData.getViewers(); + ActiveModel activeModel = entityData.getActiveModel(); + ModeledEntity modeledEntity = entityData.getModeledEntity(); + + if (activeModel.isDestroyed() || activeModel.isRemoved()) { + removed = true; + entity.remove(); + + plugin.getModelManager().getEntitiesCache().remove(modeledEntity.getBase().getEntityId()); + plugin.getModelManager().getModelEntitiesCache().remove(modeledEntity.getBase().getEntityId()); + + cancel(); + return; + } + + if (tick % 5 == 0) { + if (tick % 40 == 0) { + for (Player viewer : Set.copyOf(viewers)) { + if (!plugin.getEntityTaskManager().canSee(viewer, entityData.getEntity())) { + viewers.remove(viewer); + } + } + } + } + + tick ++; + if (tick > 400) { + tick = 0; + plugin.getEntityTaskManager().sendHitBoxToAll(entityData); + } + + if (viewers.isEmpty()) return; + + plugin.getEntityTaskManager().getPropertyHandler().sendScale(entityData, viewers, lastScale, false); + plugin.getEntityTaskManager().getPropertyHandler().sendColor(entityData, viewers, lastColor, false); + } + + @Override + public void sendEntityData(EntityData entityData, Player player, int delay) { + ModelEngineEntityData modelEngineEntityData = (ModelEngineEntityData) entityData; + + EntityUtils.setCustomEntity(player, modelEngineEntityData.getEntity().getEntityId(), plugin.getConfigManager().getConfig().getString("namespace") + ":" + modelEngineEntityData.getActiveModel().getBlueprint().getName().toLowerCase()); + + plugin.getSchedulerPool().schedule(() -> { + entityData.getEntity().sendSpawnPacket(Collections.singletonList(player)); + + plugin.getSchedulerPool().schedule(() -> { + plugin.getEntityTaskManager().getPropertyHandler().sendHitBox(entityData, player); + + plugin.getEntityTaskManager().getPropertyHandler().sendScale(entityData, Collections.singleton(player), lastScale, true); + plugin.getEntityTaskManager().getPropertyHandler().sendColor(entityData, Collections.singleton(player), lastColor, true); + + plugin.getEntityTaskManager().getPropertyHandler().updateEntityProperties(entityData, Collections.singleton(player), true); + }, 500, TimeUnit.MILLISECONDS); + }, delay * 50L, TimeUnit.MILLISECONDS); + } + + @Override + public void cancel() { + scheduledFuture.cancel(true); + } + + public void setTick(int tick) { + this.tick = tick; + } + + public void setSyncTick(int syncTick) { + this.syncTick = syncTick; + } + + public void setRemoved(boolean removed) { + this.removed = removed; + } + + public void setLastScale(float lastScale) { + this.lastScale = lastScale; + } + + public int getTick() { + return tick; + } + + public int getSyncTick() { + return syncTick; + } + + public void setLastColor(Color lastColor) { + this.lastColor = lastColor; + } + + public float getLastScale() { + return lastScale; + } + + public Color getLastColor() { + return lastColor; + } + + public boolean isRemoved() { + return removed; + } + + public ConcurrentHashMap getLastIntSet() { + return lastIntSet; + } + + public Cache getLastPlayedAnim() { + return lastPlayedAnim; + } + + public ScheduledFuture getScheduledFuture() { + return scheduledFuture; + } +} diff --git a/src/main/java/re/imc/geysermodelengine/managers/model/taskshandler/TaskHandler.java b/src/main/java/re/imc/geysermodelengine/managers/model/taskshandler/TaskHandler.java new file mode 100644 index 0000000..75ddf36 --- /dev/null +++ b/src/main/java/re/imc/geysermodelengine/managers/model/taskshandler/TaskHandler.java @@ -0,0 +1,11 @@ +package re.imc.geysermodelengine.managers.model.taskshandler; + +import org.bukkit.entity.Player; +import re.imc.geysermodelengine.managers.model.entity.EntityData; + +public interface TaskHandler { + + void runAsync(); + void sendEntityData(EntityData entityData, Player player, int delay); + void cancel(); +} diff --git a/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java b/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java index f3cf64e..db4592e 100644 --- a/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java +++ b/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java @@ -58,7 +58,6 @@ public class PacketEntity { return true; } - public void remove() { removed = true; sendEntityDestroyPacket(viewers); @@ -78,7 +77,6 @@ public class PacketEntity { } public void sendLocationPacket(Collection players) { - PacketWrapper packet; EntityPositionData data = new EntityPositionData(SpigotConversionUtil.fromBukkitLocation(location).getPosition(), Vector3d.zero(), location.getYaw(), location.getPitch()); diff --git a/src/main/java/re/imc/geysermodelengine/runnables/EntityTaskRunnable.java b/src/main/java/re/imc/geysermodelengine/runnables/EntityTaskRunnable.java deleted file mode 100644 index 3137622..0000000 --- a/src/main/java/re/imc/geysermodelengine/runnables/EntityTaskRunnable.java +++ /dev/null @@ -1,268 +0,0 @@ -package re.imc.geysermodelengine.runnables; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.ticxo.modelengine.api.animation.BlueprintAnimation; -import com.ticxo.modelengine.api.animation.handler.AnimationHandler; -import com.ticxo.modelengine.api.generator.blueprint.BlueprintBone; -import com.ticxo.modelengine.api.model.ActiveModel; -import com.ticxo.modelengine.api.model.ModeledEntity; -import com.ticxo.modelengine.api.model.bone.ModelBone; -import me.zimzaza4.geyserutils.spigot.api.EntityUtils; -import org.bukkit.entity.Player; -import re.imc.geysermodelengine.GeyserModelEngine; -import re.imc.geysermodelengine.managers.model.entity.ModelEngineEntityData; -import re.imc.geysermodelengine.packet.entity.PacketEntity; -import re.imc.geysermodelengine.util.BooleanPacker; - -import java.awt.*; -import java.util.*; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -public class EntityTaskRunnable { - - private final GeyserModelEngine plugin; - - private final ModelEngineEntityData model; - - private int tick = 0; - private int syncTick = 0; - - private float lastScale = -1.0f; - private Color lastColor = null; - - private boolean removed = false; - - private final ConcurrentHashMap lastIntSet = new ConcurrentHashMap<>(); - private final Cache lastPlayedAnim = CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MILLISECONDS).build(); - - private final ScheduledFuture scheduledFuture; - - public EntityTaskRunnable(GeyserModelEngine plugin, ModelEngineEntityData model) { - this.plugin = plugin; - - this.model = model; - - plugin.getEntityTaskManager().sendHitBoxToAll(model); - - scheduledFuture = plugin.getSchedulerPool().scheduleAtFixedRate(this::runAsync, 0, 20, TimeUnit.MILLISECONDS); - } - - public void runAsync() { - plugin.getEntityTaskManager().checkViewers(model, model.getViewers()); - - PacketEntity entity = model.getEntity(); - if (entity.isDead()) return; - - model.teleportToModel(); - - Set viewers = model.getViewers(); - ActiveModel activeModel = model.getActiveModel(); - ModeledEntity modeledEntity = model.getModeledEntity(); - - if (activeModel.isDestroyed() || activeModel.isRemoved()) { - removed = true; - entity.remove(); - - plugin.getModelManager().getEntitiesCache().remove(modeledEntity.getBase().getEntityId()); - plugin.getModelManager().getModelEntitiesCache().remove(modeledEntity.getBase().getEntityId()); - - cancel(); - return; - } - - if (tick % 5 == 0) { - if (tick % 40 == 0) { - for (Player viewer : Set.copyOf(viewers)) { - if (!plugin.getEntityTaskManager().canSee(viewer, model.getEntity())) { - viewers.remove(viewer); - } - } - } - } - - tick ++; - if (tick > 400) { - tick = 0; - plugin.getEntityTaskManager().sendHitBoxToAll(model); - } - - if (viewers.isEmpty()) return; - - plugin.getEntityTaskManager().getPropertyHandler().sendScale(model, viewers, lastScale, false); - plugin.getEntityTaskManager().getPropertyHandler().sendColor(model, viewers, lastColor, false); - } - - public void cancel() { - scheduledFuture.cancel(true); - } - - public void sendEntityData(ModelEngineEntityData model, Player player, int delay) { - EntityUtils.setCustomEntity(player, model.getEntity().getEntityId(), plugin.getConfigManager().getConfig().getString("namespace") + ":" + model.getActiveModel().getBlueprint().getName().toLowerCase()); - - plugin.getSchedulerPool().schedule(() -> { - model.getEntity().sendSpawnPacket(Collections.singletonList(player)); - - plugin.getSchedulerPool().schedule(() -> { - plugin.getEntityTaskManager().getPropertyHandler().sendHitBox(model, player); - - plugin.getEntityTaskManager().getPropertyHandler().sendScale(model, Collections.singleton(player), lastScale, true); - plugin.getEntityTaskManager().getPropertyHandler().sendColor(model, Collections.singleton(player), lastColor, true); - - updateEntityProperties(model, Collections.singleton(player), true); - }, 500, TimeUnit.MILLISECONDS); - }, delay * 50L, TimeUnit.MILLISECONDS); - } - - public void updateEntityProperties(ModelEngineEntityData model, Collection players, boolean firstSend, String... forceAnims) { - int entity = model.getEntity().getEntityId(); - Set forceAnimSet = Set.of(forceAnims); - - Map boneUpdates = new HashMap<>(); - Map animUpdates = new HashMap<>(); - Set anims = new HashSet<>(); - - model.getActiveModel().getBlueprint().getBones().forEach((s, bone) -> processBone(model, bone, boneUpdates)); - - AnimationHandler handler = model.getActiveModel().getAnimationHandler(); - Set priority = model.getActiveModel().getBlueprint().getAnimationDescendingPriority(); - for (String animId : priority) { - if (handler.isPlayingAnimation(animId)) { - BlueprintAnimation anim = model.getActiveModel().getBlueprint().getAnimations().get(animId); - - anims.add(animId); - if (anim.isOverride() && anim.getLoopMode() == BlueprintAnimation.LoopMode.ONCE) { - break; - } - } - } - - for (String id : priority) { - if (anims.contains(id)) { - animUpdates.put(id, true); - } else { - animUpdates.put(id, false); - } - } - - Set lastPlayed = new HashSet<>(lastPlayedAnim.asMap().keySet()); - - for (Map.Entry anim : animUpdates.entrySet()) { - if (anim.getValue()) { - lastPlayedAnim.put(anim.getKey(), true); - } - } - - for (String anim : lastPlayed) animUpdates.put(anim, true); - - if (boneUpdates.isEmpty() && animUpdates.isEmpty()) return; - - Map intUpdates = new HashMap<>(); - int i = 0; - - for (Integer integer : BooleanPacker.mapBooleansToInts(boneUpdates)) { - intUpdates.put(plugin.getConfigManager().getConfig().getString("namespace") + ":bone" + i, integer); - i++; - } - - i = 0; - for (Integer integer : BooleanPacker.mapBooleansToInts(animUpdates)) { - intUpdates.put(plugin.getConfigManager().getConfig().getString("namespace") + ":anim" + i, integer); - i++; - } - - if (!firstSend) { - if (intUpdates.equals(lastIntSet)) { - return; - } else { - lastIntSet.clear(); - lastIntSet.putAll(intUpdates); - } - } - - if (plugin.getConfigManager().getConfig().getBoolean("debug")) plugin.getLogger().info(animUpdates.toString()); - - List list = new ArrayList<>(boneUpdates.keySet()); - Collections.sort(list); - - for (Player player : players) { - EntityUtils.sendIntProperties(player, entity, intUpdates); - } - } - - private void processBone(ModelEngineEntityData model, BlueprintBone bone, Map map) { - String name = plugin.getEntityTaskManager().unstripName(bone).toLowerCase(); - if (name.equals("hitbox") || - name.equals("shadow") || - name.equals("mount") || - name.startsWith("p_") || - name.startsWith("b_") || - name.startsWith("ob_")) { - return; - } - - for (BlueprintBone blueprintBone : bone.getChildren().values()) processBone(model, blueprintBone, map); - - ModelBone activeBone = model.getActiveModel().getBones().get(bone.getName()); - - boolean visible = false; - if (activeBone != null) visible = activeBone.isVisible(); - - map.put(name, visible); - } - - public void setTick(int tick) { - this.tick = tick; - } - - public void setSyncTick(int syncTick) { - this.syncTick = syncTick; - } - - public void setRemoved(boolean removed) { - this.removed = removed; - } - - public void setLastScale(float lastScale) { - this.lastScale = lastScale; - } - - public int getTick() { - return tick; - } - - public int getSyncTick() { - return syncTick; - } - - public void setLastColor(Color lastColor) { - this.lastColor = lastColor; - } - - public float getLastScale() { - return lastScale; - } - - public Color getLastColor() { - return lastColor; - } - - public boolean isRemoved() { - return removed; - } - - public ConcurrentHashMap getLastIntSet() { - return lastIntSet; - } - - public Cache getLastPlayedAnim() { - return lastPlayedAnim; - } - - public ScheduledFuture getScheduledFuture() { - return scheduledFuture; - } -} diff --git a/src/main/java/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.java b/src/main/java/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.java index 7d06be9..bf48f5d 100644 --- a/src/main/java/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.java +++ b/src/main/java/re/imc/geysermodelengine/runnables/UpdateTaskRunnable.java @@ -3,7 +3,6 @@ package re.imc.geysermodelengine.runnables; import io.papermc.paper.threadedregions.scheduler.ScheduledTask; import re.imc.geysermodelengine.GeyserModelEngine; import re.imc.geysermodelengine.managers.model.entity.EntityData; -import re.imc.geysermodelengine.managers.model.entity.ModelEngineEntityData; import re.imc.geysermodelengine.managers.model.model.Model; import java.util.Map; @@ -21,7 +20,7 @@ public class UpdateTaskRunnable implements Consumer { public void accept(ScheduledTask scheduledTask) { try { for (Map models : plugin.getModelManager().getEntitiesCache().values()) { - models.values().forEach(model -> model.getEntityTask().updateEntityProperties((ModelEngineEntityData) model, model.getViewers(), false)); + models.values().forEach(entityData -> plugin.getEntityTaskManager().getPropertyHandler().updateEntityProperties(entityData, entityData.getViewers(), false)); } } catch (Throwable err) { throw new RuntimeException(err); diff --git a/src/main/resources/paper-plugin.yml b/src/main/resources/paper-plugin.yml index ac71c2f..d98343d 100644 --- a/src/main/resources/paper-plugin.yml +++ b/src/main/resources/paper-plugin.yml @@ -6,6 +6,7 @@ api-version: '1.21' authors: - zimzaza4 - willem.dev + - xSquishyLiam load: STARTUP @@ -19,7 +20,5 @@ dependencies: required: true ModelEngine: required: false - join-classpath: true BetterModel: - required: false - join-classpath: true \ No newline at end of file + required: false \ No newline at end of file