diff --git a/README.md b/README.md
index c48f9af..5ffc24e 100644
--- a/README.md
+++ b/README.md
@@ -1,107 +1,67 @@
-# GeyserModelEngine 自定义实体分支
+# GeyserModelEngine
+# About
-> GitHub仓库:[https://github.com/zimzaza4/GeyserModelEngine/tree/custom-entity](https://github.com/zimzaza4/GeyserModelEngine/tree/custom-entity)
+Thanks to [Willem](https://github.com/OmeWillem/GeyserUtils) for adding the following features:
+- Part Visibility
+- Color support
+- Scaling support
+- & more
-> [Discord](https://discord.gg/NNNaUdAbpP)
----
+# How To Install
-🌏 Language 🌏
+Download the following plugins according to what server software you use.
-[[English](README_EN.md)] [[简体中文](README.md)] [欢迎贡献更多语言]
-
----
-
-# 这个跟主分支有什么区别?
-
-跟主分支不同的是,这个是真正的自定义实体!!!🎉🎉🎉
-
-而主分支是给BE生成个史蒂夫发送4d皮肤给be玩家,支持原版Geyser
-
-只需要往资源包里塞动画文件即可,可以有效防止那些进服下个资源包就跑白嫖你模型的贼,但同时限制也挺多😥
-
-总之两者各有各优势,根据各服务器情况选择
-
----
-
-# 如何安装
-
-根据服务端版本下载以下插件
-
-| 插件 | 链接 | 作用 |
+| plugins | Link | effect |
| :--- | :---- | :--- |
-| GeyserUtils | [Github](https://github.com/zimzaza4/GeyserUtils) | 让你的Geyser支持调用一些BE的东西 |
-| GeyserModelEngine | [Github](https://github.com/zimzaza4/GeyserModelEngine) | 你猜 |
-| GeyserModelEnginePackGenerator | [Github](https://github.com/zimzaza4/GeyserModelEnginePackGenerator) | 帮你自动转换模型生成资源包 |
+| GeyserUtils | [Github](https://github.com/OmeWillem/GeyserUtils) | Get your Geyser to support calling some BE stuff |
+| GeyserModelEngine | [Github](https://github.com/OmeWillem/GeyserModelEngine) | Make your bedrock support MEG4 |
+| GeyserModelEnginePackGenerator | [Github](https://github.com/OmeWillem/GeyserModelEnginePackGenerator) | Help you automatically transform the model to generate resource packs |
-下载完后,将`GeyserModelEngine` `Geyser自定义实体分支`放入插件文件夹
+- Put `GeyserModelEngine` in the plugins folder (only Spigot or forks of Spigot supported)
+- Put either `geyserutils-spigot` in your plugins folder aswell (`geyserutils-velocity` in your Velocity plugins folder if you use it)
+- Put `GeyserModelEnginePackGenerator` and `geyserutils-geyser` into `plugins/[Geyser-Folder]/extensions`
-根据服务端版本把`geyserutils-spigot`/`velocity`/`bungeecord`放入插件文件夹
+Start the server to generate the relevant configuration files, and then shut down the server to convert any models.
-`GeyserModelEnginePackGenerator` `geyserutils-geyser`放入geyser的扩展文件夹
+# Convert Models
-先启动服务器生成相关配置文件,之后关闭服务器就安装好了
+`GeyserModelEnginePackGenerator` is capable of generating models all by itself. After generating it will also apply this pack automatically.
-当然,先别急着用,现在你还得接着读下去
-
----
-
-# 转换模型📦
-
-现在`GeyserModelEnginePackGenerator`长大了学会自己转换模型生成资源包了
-
-我们来到以下路径 `plugins/Geyser-Spigot/extensions/geysermodelenginepackgenerator/input/`
-
-在此目录创建一个文件夹名为模型的ID,比如我有个模型id为`parry_knight`,那就命名为`parry_knight`
+- First go to `plugins/[Geyser-Folder]/extensions/geysermodelenginepackgenerator/input/`
+- Create a folder in this directory with the ID of the model. (this is the same name as your model within ModelEngine 4.)
-> 每个模型都要有独立的模型文件夹
+> Each model should have a separate model folder
-新版本BlockBench 导出的基岩版模型format_version 是1.21.0
-需要手动改成1.12.0
-否则你的客户端看不到模型
+- Now use BlockBench and convert your model to a Bedrock Entity, this will allow you to export the Bedrock Geometry and Animations.
+- Put the geometry, animations and texture file in this folder you've made.
-我们将模型、动画和纹理全部原封不动丢进这个文件夹
+> The new version of BlockBench exports the bedrock model format_version as `1.21.0`.
+> You need to change it to `1.12.0` manually.
+> Otherwise your client will NOT see the model.
-重启服务器或者重载geyser让他开始生成资源包
-
-来到`plugins/Geyser-Spigot/extensions/geysermodelenginepackgenerator`目录
-
-这里你会看见多了个`generated_pack.zip`,那就说明打包好了
+- Restart the server or reload geyser to start generating the resource pack.
+- Go to `plugins/[Geyser-Folder]/extensions/geysermodelenginepackgenerator`, and you should see your pack generated!
-最后一步,重载Geyser或者重启服务器加载资源包
+- Final step, reload Geyser or restart the server to load the resource pack.
+- Congratulations, you've completed this tutorial!
-现在可以用基岩版进服下载资源包看看是否正常生效了
+# Tips
----
+* Pay attention! The pack only regenerates when the number of models changes, you can technically speaking remove the generated_pack folder to force a reload aswell.
+* You do not have to manually put the pack into the packs folder of Geyser, the extension is capable of loading the pack itself.
-# 注意事项❗
+# Current issues
-* `geysermodelenginepackgenerator`是检测模型的数量有变更才会执行转换打包指令,想重新生成资源包建议先删掉`generated_pack.zip`然后重启服务器重新生成资源包。记得改uuid或版本号!!!
-* 在新版本中不用把这个包丢进`geyser/packs`目录,他会自己加载上
+* Multi-textures are not supported
+* Please report any bugs (discord: https://discord.gg/NNNaUdAbpP)
----
+# FAQ
-# 完结🤗
-
-恭喜你现在学会如何使用了😎有BUG或建议请发Issues
-
----
-
-# 当前限制💢
-
-* 不支持多纹理
-* 头部旋转跟JE不太同步
-* 待挖掘
-
----
-
-# 常见问题❓
-
-### 召唤模型后召唤的并非模型而是史蒂夫?
-
-如果你确定你根据上面的教程一步一步做了,可能是这个模型的问题?
+### Where can I contact you?
+You can contact me on our Discord: https://discord.gg/NNNaUdAbpP
diff --git a/README_EN.md b/README_EN.md
deleted file mode 100644
index 8de0a7d..0000000
--- a/README_EN.md
+++ /dev/null
@@ -1,83 +0,0 @@
-# GeyserModelEngine CustomEntity Fork
-
-> GitHub:[https://github.com/zimzaza4/GeyserModelEngine/tree/custom-entity](https://github.com/zimzaza4/GeyserModelEngine/tree/custom-entity)
-
-🌏 [[English](README_EN.md)] [[简体中文](README.md)] [Welcome to contribute more languages]
-
-# About
-
-this is for [GeyserCustomEntityFork](https://github.com/zimzaza4/Geyser)'s version,no support vanilla Geyser
-
-Unlike the master, this one is truly a custom entity
-
-# how to install
-
-Download the following plugins according to the server core
-
-| plugins | Link | effect |
-| :--- | :---- | :--- |
-| GeyserUtils | [Github](https://github.com/zimzaza4/GeyserUtils) | Get your Geyser to support calling some BE stuff |
-| GeyserModelEngine | [Github](https://github.com/zimzaza4/GeyserModelEngine) | Make your bedrock support MEG4 |
-| GeyserModelEnginePackGenerator | [Github](https://github.com/zimzaza4/GeyserModelEnginePackGenerator) | Help you automatically transform the model to generate resource packs |
-
-replace your Geyser with that Geyser fork
-
-put `GeyserModelEngine` in the plugins folder (only spigot)
-
-and `geyserutils-spigot`/`velocity`/`bungeecord`
-
-`GeyserModelEnginePackGenerator` `geyserutils-geyser` put into `plugins/geyser/extensions`
-
-Start the server to generate the relevant configuration files, and then shut down the server to install
-
-# convert model
-
-`GeyserModelEnginePackGenerator` can generate resource packs himself
-
-We came to `plugins/Geyser-Spigot/extensions/geysermodelenginepackgenerator/input/`
-
-Create a folder in this directory called the ID of the model.
-
-For example, if I have a model with the id `parry_knight`, name it `parry_knight`
-
-
-
-> Each model should have a separate model folder
-
-Then drop the model, animations, and textures into this folder intact
-
-The new version of BlockBench exports the bedrock model format_version as `1.21.0`
-You need to change it to `1.12.0` manually
-Otherwise your client will not see the model
-
-
-
-Restart the server or reload geyser to start generating resource packs
-
-go to `plugins/Geyser-Spigot/extensions/geysermodelenginepackgenerator`
-
-
-
-final step, reload Geyser or restart the server to load the resource pack
-
-# tips
-
-* Pay attention! It is packaged by detecting the number of models and will not execute if the number does not change.
-* To repackage it is recommended to delete `generated_pack.zip` and change the uuid or version
-* instead of dropping the package into the `geyser/packs` directory, it will load pack itself
-
-# The end
-
-Congratulations you now learn how to use, any bugs please send Issues
-
-# limit
-
-* Multi-textures are not supported
-* To be excavated
-
-# FAQ
-
-### Why does it turn into Steve after summoning a model?
-
-If you're sure you did it step by step according to the tutorial above, there may be a problem with this model?
-
diff --git a/libs/geyserutils-spigot-1.0-SNAPSHOT.jar b/libs/geyserutils-spigot-1.0-SNAPSHOT.jar
index ec7de3a..b263621 100644
Binary files a/libs/geyserutils-spigot-1.0-SNAPSHOT.jar and b/libs/geyserutils-spigot-1.0-SNAPSHOT.jar differ
diff --git a/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java b/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java
index ef7814c..03778ff 100644
--- a/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java
+++ b/src/main/java/re/imc/geysermodelengine/GeyserModelEngine.java
@@ -16,7 +16,6 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
-import re.imc.geysermodelengine.listener.AddEntityPacketListener;
import re.imc.geysermodelengine.listener.ModelListener;
import re.imc.geysermodelengine.listener.MountPacketListener;
import re.imc.geysermodelengine.model.ModelEntity;
@@ -35,7 +34,7 @@ public final class GeyserModelEngine extends JavaPlugin {
private static boolean alwaysSendSkin;
@Getter
- private int skinSendDelay;
+ private int sendDelay;
@Getter
private int viewDistance;
@@ -46,16 +45,6 @@ public final class GeyserModelEngine extends JavaPlugin {
@Getter
private Cache joinedPlayer;
- @Getter
- @Setter
- private boolean spawningModelEntity = false;
-
-
- @Getter
- @Setter
- private ModelEntity currentModel = null;
-
-
@Getter
private int joinSendDelay;
@@ -72,8 +61,8 @@ public final class GeyserModelEngine extends JavaPlugin {
// Plugin startup logic
saveDefaultConfig();
// alwaysSendSkin = getConfig().getBoolean("always-send-skin");
- skinSendDelay = getConfig().getInt("skin-send-delay", 0);
- viewDistance = getConfig().getInt("skin-view-distance", 60);
+ sendDelay = getConfig().getInt("data-send-delay", 0);
+ viewDistance = getConfig().getInt("entity-view-distance", 60);
debug = getConfig().getBoolean("debug", false);
modelEntityType = EntityType.valueOf(getConfig().getString("model-entity-type", "BAT"));
joinSendDelay = getConfig().getInt("join-send-delay", 20);
@@ -82,7 +71,7 @@ public final class GeyserModelEngine extends JavaPlugin {
.expireAfterWrite(joinSendDelay * 50L, TimeUnit.MILLISECONDS).build();
}
instance = this;
- ProtocolLibrary.getProtocolManager().addPacketListener(new AddEntityPacketListener());
+ // ProtocolLibrary.getProtocolManager().addPacketListener(new AddEntityPacketListener());
ProtocolLibrary.getProtocolManager().addPacketListener(new MountPacketListener());
Bukkit.getPluginManager().registerEvents(new ModelListener(), this);
diff --git a/src/main/java/re/imc/geysermodelengine/listener/AddEntityPacketListener.java b/src/main/java/re/imc/geysermodelengine/listener/AddEntityPacketListener.java
deleted file mode 100644
index fb22064..0000000
--- a/src/main/java/re/imc/geysermodelengine/listener/AddEntityPacketListener.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package re.imc.geysermodelengine.listener;
-
-import com.comphenix.protocol.PacketType;
-import com.comphenix.protocol.ProtocolLibrary;
-import com.comphenix.protocol.events.*;
-import com.comphenix.protocol.reflect.StructureModifier;
-import com.comphenix.protocol.wrappers.WrappedWatchableObject;
-import com.ticxo.modelengine.api.ModelEngineAPI;
-import com.ticxo.modelengine.api.entity.BukkitEntity;
-import com.ticxo.modelengine.api.entity.Hitbox;
-import com.ticxo.modelengine.api.interaction.DynamicHitbox;
-import com.ticxo.modelengine.api.interaction.InteractionTracker;
-import com.ticxo.modelengine.api.model.bone.type.SubHitbox;
-import com.ticxo.modelengine.api.nms.entity.HitboxEntity;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.EntityType;
-import org.geysermc.floodgate.api.FloodgateApi;
-import org.jetbrains.annotations.NotNull;
-import re.imc.geysermodelengine.GeyserModelEngine;
-import re.imc.geysermodelengine.model.EntityTask;
-import re.imc.geysermodelengine.model.ModelEntity;
-
-import java.util.Set;
-import java.util.UUID;
-
-public class AddEntityPacketListener extends PacketAdapter {
- public AddEntityPacketListener() {
- super(GeyserModelEngine.getInstance(), ListenerPriority.HIGHEST, Set.of(PacketType.Play.Server.SPAWN_ENTITY), ListenerOptions.SYNC);
- }
-
- @Override
- public void onPacketSending(PacketEvent event) {
-
- PacketContainer packet = event.getPacket();
- StructureModifier modifier = packet.getEntityModifier(event);
- Entity entity = modifier.readSafely(0);
-
- if (entity == null) {
- return;
- }
- boolean isBedrock = FloodgateApi.getInstance().isFloodgatePlayer(event.getPlayer().getUniqueId());
- ModelEntity model = ModelEntity.MODEL_ENTITIES.get(entity.getEntityId());
-
-
- if (model != null) {
- if (isBedrock) {
- if (packet.getMeta("delayed").isPresent()) {
- if (model.getTask().isLooping()) {
-
- String lastAnimation = model.getTask().getLastAnimation();
- model.getTask().playBedrockAnimation(lastAnimation, Set.of(event.getPlayer()), true, 0f);
- }
- return;
- }
-
- EntityTask task = model.getTask();
- int delay = 1;
- boolean firstJoined = GeyserModelEngine.getInstance().getJoinedPlayer().getIfPresent(event.getPlayer()) != null;
- if (firstJoined) {
- delay = GeyserModelEngine.getInstance().getJoinSendDelay();
- }
- if (task == null || firstJoined) {
- Bukkit.getScheduler().runTaskLater(GeyserModelEngine.getInstance(), () -> {
- model.getTask().sendEntityData(event.getPlayer(), GeyserModelEngine.getInstance().getSkinSendDelay());
- }, delay);
- } else {
- task.sendEntityData(event.getPlayer(), GeyserModelEngine.getInstance().getSkinSendDelay());
- }
-
- event.setCancelled(true);
-
- Bukkit.getScheduler().runTaskLater(GeyserModelEngine.getInstance(), () -> {
- packet.setMeta("delayed", 1);
- ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet);
- }, delay + 2);
- } else {
- event.setCancelled(true);
- }
- }
- }
-}
diff --git a/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java b/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java
index 0706c72..c50e01a 100644
--- a/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java
+++ b/src/main/java/re/imc/geysermodelengine/listener/ModelListener.java
@@ -97,44 +97,7 @@ public class ModelListener implements Listener {
}
}
- @EventHandler
- public void onModelHurt(EntityDamageEvent event) {
- ModelEntity model = ModelEntity.MODEL_ENTITIES.get(event.getEntity().getEntityId());
- if (model != null) {
- if (!event.getEntity().hasMetadata("show_damage")) {
- event.setCancelled(true);
- }
- event.getEntity().removeMetadata("show_damage", GeyserModelEngine.getInstance());
- if (!model.getEntity().isDead()) {
- event.setDamage(0);
- model.getEntity().setHealth(model.getEntity().getMaxHealth());
- }
- }
- }
-
-
- @EventHandler(priority = EventPriority.HIGHEST)
- public void onModelEntitySpawn(EntitySpawnEvent event) {
- if (GeyserModelEngine.getInstance().isSpawningModelEntity() && event.getEntity() instanceof LivingEntity entity) {
- if (event.isCancelled()) {
- event.setCancelled(false);
- }
- ModelEntity model = GeyserModelEngine.getInstance().getCurrentModel();
- int id = entity.getEntityId();
- ActiveModel activeModel = model.getActiveModel();
- ModelEntity.MODEL_ENTITIES.put(id, model);
- model.applyFeatures(entity, "model." + activeModel.getBlueprint().getName());
- GeyserModelEngine.getInstance().setCurrentModel(null);
- GeyserModelEngine.getInstance().setSpawningModelEntity(false);
-
- for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
- if (FloodgateApi.getInstance().isFloodgatePlayer(onlinePlayer.getUniqueId())) {
- PlayerUtils.setCustomEntity(onlinePlayer, entity.getEntityId(), "modelengine:" + model.getActiveModel().getBlueprint().getName().toLowerCase());
- }
- }
- }
- }
@EventHandler
public void onModelEntityHurt(EntityDamageEvent event) {
@@ -142,8 +105,7 @@ public class ModelListener implements Listener {
if (model != null) {
for (Map.Entry entry : model.entrySet()) {
if (!entry.getValue().getEntity().isDead()) {
- entry.getValue().getEntity().setMetadata("show_damage", new FixedMetadataValue(GeyserModelEngine.getInstance(), true));
- entry.getValue().getEntity().damage(0);
+ entry.getValue().getEntity().sendHurtPacket(entry.getValue().getViewers());
}
}
@@ -164,20 +126,6 @@ public class ModelListener implements Listener {
*/
- @EventHandler
- public void onModelHit(ProjectileHitEvent event) {
- if (event.getHitEntity() == null) {
- return;
- }
- ModelEntity model = ModelEntity.MODEL_ENTITIES.get(event.getHitEntity().getEntityId());
- if (model != null) {
-
- event.setCancelled(true);
- model.getEntity().setHealth(model.getEntity().getMaxHealth());
-
- }
- }
-
@EventHandler
public void onAnimationEnd(AnimationEndEvent event) {
diff --git a/src/main/java/re/imc/geysermodelengine/listener/MountPacketListener.java b/src/main/java/re/imc/geysermodelengine/listener/MountPacketListener.java
index 7d1dbb7..cfdab1a 100644
--- a/src/main/java/re/imc/geysermodelengine/listener/MountPacketListener.java
+++ b/src/main/java/re/imc/geysermodelengine/listener/MountPacketListener.java
@@ -41,15 +41,12 @@ public class MountPacketListener extends PacketAdapter {
if (event.getPlayer().getInventory().getHeldItemSlot() == 0) {
event.getPacket().getBooleans().writeSafely(0, true);
event.getPlayer().getInventory().setHeldItemSlot(3);
- event.getPlayer().sendActionBar("jump");
}
if (pitch > 89 || event.getPlayer().getInventory().getHeldItemSlot() == 1) {
event.getPacket().getBooleans().writeSafely(1, true);
- event.getPlayer().sendActionBar("shift");
}
if (event.getPlayer().getInventory().getHeldItemSlot() == 8) {
event.getPacket().getBooleans().writeSafely(0, true);
- event.getPlayer().sendActionBar("hold jump");
}
}
}
diff --git a/src/main/java/re/imc/geysermodelengine/model/EntityTask.java b/src/main/java/re/imc/geysermodelengine/model/EntityTask.java
index 452d54c..e33aba5 100644
--- a/src/main/java/re/imc/geysermodelengine/model/EntityTask.java
+++ b/src/main/java/re/imc/geysermodelengine/model/EntityTask.java
@@ -2,9 +2,9 @@ package re.imc.geysermodelengine.model;
import com.ticxo.modelengine.api.animation.BlueprintAnimation;
import com.ticxo.modelengine.api.entity.BaseEntity;
-import com.ticxo.modelengine.api.entity.BukkitEntity;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
+import com.ticxo.modelengine.api.model.bone.ModelBone;
import lombok.Getter;
import lombok.Setter;
import me.zimzaza4.geyserutils.common.animation.Animation;
@@ -13,13 +13,13 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
-import org.bukkit.util.BoundingBox;
import org.geysermc.floodgate.api.FloodgateApi;
-import org.jetbrains.annotations.NotNull;
+import org.joml.Vector3f;
import re.imc.geysermodelengine.GeyserModelEngine;
-import re.imc.geysermodelengine.listener.ModelListener;
+import re.imc.geysermodelengine.packet.entity.PacketEntity;
-import java.util.Set;
+import java.awt.*;
+import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import static re.imc.geysermodelengine.model.ModelEntity.ENTITIES;
@@ -37,11 +37,18 @@ public class EntityTask {
AtomicInteger animationCooldown = new AtomicInteger(0);
AtomicInteger currentAnimationPriority = new AtomicInteger(0);
- boolean firstAnimation = true;
boolean spawnAnimationPlayed = false;
boolean removed = false;
+ float lastScale = -1.0f;
+ Color lastColor = null;
+ Map lastModelBoneSet = new HashMap<>();
+
+
String lastAnimation = "";
+ String currentAnimProperty = "anim_spawn";
+ String lastAnimProperty = "";
+
boolean looping = true;
private BukkitRunnable syncTask;
@@ -52,39 +59,17 @@ public class EntityTask {
public EntityTask(ModelEntity model) {
this.model = model;
}
-
- public void runSync() {
-
- syncTick ++;
- if (syncTick > 400) {
- syncTick = 0;
- }
-
- if (syncTick % 5 == 0) {
-
- for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
- if (!FloodgateApi.getInstance().isFloodgatePlayer(onlinePlayer.getUniqueId())) {
- onlinePlayer.hideEntity(GeyserModelEngine.getInstance(), model.getEntity());
- }
- }
- }
-
- if (!removed && model.getEntity().isDead() && model.getModeledEntity().getBase().isAlive() && !model.getActiveModel().isRemoved()) {
- // model.spawnEntity();
- }
-
- model.getEntity().setVisualFire(false);
- model.teleportToModel();
- }
public void runAsync() {
- Entity entity = model.getEntity();
+ PacketEntity entity = model.getEntity();
if (entity.isDead()) {
return;
}
+
+ model.teleportToModel();
Set viewers = model.getViewers();
ActiveModel activeModel = model.getActiveModel();
ModeledEntity modeledEntity = model.getModeledEntity();
- if (activeModel.isRemoved() || !modeledEntity.getBase().isAlive()) {
+ if (activeModel.isDestroyed() || activeModel.isRemoved() || !modeledEntity.getBase().isAlive()) {
if (!activeModel.isRemoved() && hasAnimation("death")) {
new BukkitRunnable() {
@Override
@@ -108,26 +93,12 @@ public class EntityTask {
cancel();
return;
}
- /*
- if (model.getEntity().isDead()) {
- ENTITIES.remove(modeledEntity.getBase().getEntityId());
- MODEL_ENTITIES.remove(entity.getEntityId());
- cancel();
- return;
- }
-
- */
- /*
- if (waitingTick > 0) {
- waitingTick--;
- }
- */
if (!spawnAnimationPlayed) {
spawnAnimationPlayed = true;
}
- if (tick > 1 && tick % 5 == 0) {
+ if (tick % 5 == 0) {
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (FloodgateApi.getInstance().isFloodgatePlayer(onlinePlayer.getUniqueId())) {
@@ -135,22 +106,14 @@ public class EntityTask {
if (canSee(onlinePlayer, model.getEntity())) {
if (!viewers.contains(onlinePlayer)) {
+ sendSpawnPacket(onlinePlayer);
viewers.add(onlinePlayer);
- /*
- if (GeyserModelEngine.getInstance().getSkinSendDelay() > 0) {
- sendEntityData(onlinePlayer, GeyserModelEngine.getInstance().getSkinSendDelay());
- } else {
- PlayerUtils.sendCustomSkin(onlinePlayer, model.getEntity(), activeModel.getBlueprint().getName());
-
- Bukkit.getScheduler().runTaskLaterAsynchronously(GeyserModelEngine.getInstance(), () -> {
- sendHitBox(onlinePlayer);
- }, 2);
- }
-
- */
}
} else {
- viewers.remove(onlinePlayer);
+ if (viewers.contains(onlinePlayer)) {
+ entity.sendEntityDestroyPacket(Collections.singletonList(onlinePlayer));
+ viewers.remove(onlinePlayer);
+ }
}
}
}
@@ -162,20 +125,10 @@ public class EntityTask {
if (!canSee(viewer, model.getEntity())) {
viewers.remove(viewer);
}
-
- /*
-
- if (GeyserModelEngine.isAlwaysSendSkin()) {
- PlayerUtils.sendCustomSkin(viewer, model.getEntity(), activeModel.getBlueprint().getName());
-
- }
-
- */
}
}
}
-
tick ++;
if (tick > 400) {
tick = 0;
@@ -191,35 +144,123 @@ public class EntityTask {
} else if (base.isJumping() && hasAnimation("jump")) {
playAnimation("jump", 30);
} else if (base.isWalking() && hasAnimation("walk")) {
- playAnimation("walk", 20);
+ setAnimationProperty("modelengine:anim_walk");
+ // playAnimation("walk", 20);
} else if (hasAnimation("idle")) {
- playAnimation("idle", 0);
+ // playAnimation("idle", 0);
+ setAnimationProperty("modelengine:anim_idle");
}
if (animationCooldown.get() > 0) {
animationCooldown.decrementAndGet();
}
+
+ Optional player = viewers.stream().findAny();
+ if (player.isEmpty()) return;
+
+ // i think properties need send to all players
+ // because lastSet
+ viewers.forEach(viewer -> updateEntityProperties(player.get(), false));
+
+ // do not actually use this, atleast bundle these up ;(
+ sendScale(player.get(), true);
+ sendColor(player.get(), true);
+ }
+
+ private void sendSpawnPacket(Player onlinePlayer) {
+ EntityTask task = model.getTask();
+ int delay = 1;
+ boolean firstJoined = GeyserModelEngine.getInstance().getJoinedPlayer().getIfPresent(onlinePlayer) != null;
+ if (firstJoined) {
+ delay = GeyserModelEngine.getInstance().getJoinSendDelay();
+ }
+ if (task == null || firstJoined) {
+ Bukkit.getScheduler().runTaskLaterAsynchronously(GeyserModelEngine.getInstance(), () -> {
+ model.getTask().sendEntityData(onlinePlayer, GeyserModelEngine.getInstance().getSendDelay());
+ }, delay);
+ } else {
+ task.sendEntityData(onlinePlayer, GeyserModelEngine.getInstance().getSendDelay());
+ }
}
public void sendEntityData(Player player, int delay) {
- // System.out.println("TYPE: " + "modelengine:" + model.getActiveModel().getBlueprint().getName().toLowerCase());
PlayerUtils.setCustomEntity(player, model.getEntity().getEntityId(), "modelengine:" + model.getActiveModel().getBlueprint().getName().toLowerCase());
Bukkit.getScheduler().runTaskLaterAsynchronously(GeyserModelEngine.getInstance(), () -> {
// PlayerUtils.sendCustomSkin(player, model.getEntity(), model.getActiveModel().getBlueprint().getName());
- if (looping) {
- playBedrockAnimation(lastAnimation, Set.of(player), looping, 0f);
- }
- sendHitBox(player);
- sendScale(player);
+ model.getEntity().sendSpawnPacket(Collections.singletonList(player));
+
Bukkit.getScheduler().runTaskLaterAsynchronously(GeyserModelEngine.getInstance(), () -> {
+ if (looping) {
+ playBedrockAnimation(lastAnimation, Set.of(player), looping, 0f);
+ }
sendHitBox(player);
+ sendScale(player, true);
+ updateEntityProperties(player, true);
}, 8);
}, delay);
}
- public void sendScale(Player player) {
- // todo?
+ public void sendScale(Player player, boolean ignore) {
+ if (player == null) return;
+
+ Vector3f scale = model.getActiveModel().getScale();
+ float average = (scale.x + scale.y + scale.z) / 3;
+ if (average == lastScale) return;
+
+ PlayerUtils.sendCustomScale(player, model.getEntity(), average);
+
+ if (ignore) return;
+ lastScale = average;
+ }
+
+ public void sendColor(Player player, boolean ignore) {
+ if (player == null) return;
+
+ Color color = new Color(model.getActiveModel().getDefaultTint().asARGB());
+ if (color.equals(lastColor)) return;
+
+ PlayerUtils.sendCustomColor(player, model.getEntity(), color);
+
+ if (ignore) return;
+ lastColor = color;
+ }
+
+ public void setAnimationProperty(String currentAnimProperty) {
+ this.lastAnimProperty = currentAnimProperty;
+ this.currentAnimProperty = currentAnimProperty;
+ }
+
+ public void updateEntityProperties(Player player, boolean ignore) {
+ Entity entity = model.getEntity();
+
+ Map updates = new HashMap<>();
+ model.getActiveModel().getBones().forEach((s,bone) -> {
+ if (!lastModelBoneSet.containsKey(bone)) lastModelBoneSet.put(bone, !bone.isVisible());
+
+ if (!lastModelBoneSet.get(bone).equals(bone.isVisible()) || ignore) {
+ String name = unstripName(bone).toLowerCase();
+ updates.put(model.getActiveModel().getBlueprint().getName() + ":" + name, bone.isVisible());
+ lastModelBoneSet.replace(bone, bone.isVisible());
+ }
+
+ });
+ if (ignore || !lastAnimProperty.equals(currentAnimProperty)) {
+ updates.put(lastAnimProperty, false);
+ updates.put(currentAnimProperty, true);
+ }
+ if (updates.isEmpty()) return;
+ PlayerUtils.sendBoolProperties(player, entity, updates);
+ }
+
+ private String unstripName(ModelBone bone) {
+ String name = bone.getBoneId();
+ if (bone.getBlueprintBone().getBehaviors().get("head") != null) {
+ if (!bone.getBlueprintBone().getBehaviors().get("head").isEmpty()) return "hi_" + name;
+ return "h_" + name;
+ }
+
+ return name;
}
public void sendHitBoxToAll() {
@@ -262,17 +303,10 @@ public class EntityTask {
} else if (animationCooldown.get() == 0) {
play = true;
}
- boolean delaySend = false;
- if (firstAnimation) {
- delaySend = true;
- firstAnimation = false;
- }
- boolean lastLoopState = looping;
looping = forceLoop || animationProperty.getLoopMode() == BlueprintAnimation.LoopMode.LOOP;;
if (lastAnimation.equals(animation)) {
if (looping) {
- // play = waitingTick == 1;
play = false;
}
}
@@ -280,34 +314,20 @@ public class EntityTask {
if (play) {
+ setAnimationProperty("modelengine:anim_stop");
+ model.getViewers().forEach(viewer -> updateEntityProperties(viewer, false));
currentAnimationPriority.set(p);
- if (lastLoopState && !lastAnimation.equals(animation)) {
- // clearLoopAnimation();
- // delaySend = true;
- }
-
String id = "animation." + activeModel.getBlueprint().getName().toLowerCase() + "." + animationProperty.getName().toLowerCase();
lastAnimation = id;
animationCooldown.set((int) (animationProperty.getLength() * 20));
- if (delaySend) {
- Bukkit.getScheduler().runTaskLaterAsynchronously(GeyserModelEngine.getInstance(), () -> playBedrockAnimation(id, model.getViewers(), looping, blendTime), 0);
- } else {
- playBedrockAnimation(id, model.getViewers(), looping, blendTime);
- }
+ playBedrockAnimation(id, model.getViewers(), looping, blendTime);
}
return animationCooldown.get();
}
- /*
- private void clearLoopAnimation() {
- playStopBedrockAnimation(lastAnimation);
-
- }
-
-
- private void playStopBedrockAnimation(String animationId) {
+ public void playStopBedrockAnimation(String animationId) {
Entity entity = model.getEntity();
Set viewers = model.getViewers();
@@ -328,7 +348,7 @@ public class EntityTask {
}
- */
+
public void playBedrockAnimation(String animationId, Set viewers, boolean loop, float blendTime) {
// model.getViewers().forEach(viewer -> viewer.sendActionBar("CURRENT AN:" + animationId));
@@ -355,9 +375,6 @@ public class EntityTask {
if (player.isDead()) {
return false;
}
- if (player.getWorld() != entity.getWorld()) {
- return false;
- }
if (GeyserModelEngine.getInstance().getJoinedPlayer() != null && GeyserModelEngine.getInstance().getJoinedPlayer().getIfPresent(player) != null) {
return false;
}
@@ -377,7 +394,7 @@ public class EntityTask {
}
public void cancel() {
- syncTask.cancel();
+ // syncTask.cancel();
asyncTask.cancel();
}
@@ -393,13 +410,6 @@ public class EntityTask {
lastAnimation = id;
sendHitBoxToAll();
- syncTask = new BukkitRunnable() {
- @Override
- public void run() {
- runSync();
- }
- };
- syncTask.runTaskTimer(instance, i, 0);
asyncTask = new BukkitRunnable() {
@Override
diff --git a/src/main/java/re/imc/geysermodelengine/model/ModelEntity.java b/src/main/java/re/imc/geysermodelengine/model/ModelEntity.java
index 1025ddb..c175edd 100644
--- a/src/main/java/re/imc/geysermodelengine/model/ModelEntity.java
+++ b/src/main/java/re/imc/geysermodelengine/model/ModelEntity.java
@@ -1,8 +1,6 @@
package re.imc.geysermodelengine.model;
import com.google.common.collect.Sets;
-import com.ticxo.modelengine.api.ModelEngineAPI;
-import com.ticxo.modelengine.api.entity.BukkitEntity;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
import lombok.Getter;
@@ -10,8 +8,8 @@ import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue;
-import org.bukkit.util.Vector;
import re.imc.geysermodelengine.GeyserModelEngine;
+import re.imc.geysermodelengine.packet.entity.PacketEntity;
import java.util.HashMap;
import java.util.Map;
@@ -25,8 +23,7 @@ public class ModelEntity {
public static Map MODEL_ENTITIES = new ConcurrentHashMap<>();
- private LivingEntity entity;
- private BukkitEntity controllerEntity;
+ private PacketEntity entity;
private final Set viewers = Sets.newConcurrentHashSet();
@@ -41,29 +38,11 @@ public class ModelEntity {
this.activeModel = model;
this.entity = spawnEntity();
runEntityTask();
-
}
public void teleportToModel() {
Location location = modeledEntity.getBase().getLocation();
- /*
- location.setPitch(modeledEntity.getXHeadRot());
- location.setYaw(modeledEntity.getYHeadRot());
- for (Player viewer : viewers) {
- viewer.sendActionBar("X:" + modeledEntity.getXHeadRot() + ", Y:" + modeledEntity.getYHeadRot());
- }
-
- */
- Vector vector = modeledEntity.getBase().getMoveController().getVelocity();
- ModelEngineAPI.getEntityHandler().setPosition(entity, location.getX(), location.getY(), location.getZ());
- // ModelEngineAPI.getEntityHandler().movePassenger(entity, location.getX(), location.getY(), location.getZ());
- controllerEntity.getMoveController().setVelocity(vector.getX(), vector.getY(), vector.getZ());
- if (modeledEntity.getBase() instanceof BukkitEntity bukkitEntity && bukkitEntity.getOriginal() instanceof LivingEntity livingEntity) {
- controllerEntity.getLookController().setHeadYaw(livingEntity.getEyeLocation().getYaw());
- controllerEntity.getLookController().setPitch(livingEntity.getEyeLocation().getPitch());
- controllerEntity.getLookController().setBodyYaw(livingEntity.getBodyYaw());
- }
-
+ entity.teleport(location);
}
public static ModelEntity create(ModeledEntity entity, ActiveModel model) {
ModelEntity modelEntity = new ModelEntity(entity, model);
@@ -79,14 +58,8 @@ public class ModelEntity {
return modelEntity;
}
- public LivingEntity spawnEntity() {
- ModelEntity model = this;
- // int lastEntityId = ReflectionManager.getNewEntityId();
- // System.out.println("RID:" + entityId);
- GeyserModelEngine.getInstance().setSpawningModelEntity(true);
- GeyserModelEngine.getInstance().setCurrentModel(model);
- entity = (LivingEntity) modeledEntity.getBase().getLocation().getWorld().spawnEntity(modeledEntity.getBase().getLocation(), GeyserModelEngine.getInstance().getModelEntityType());
- controllerEntity = new BukkitEntity(entity);
+ public PacketEntity spawnEntity() {
+ entity = new PacketEntity(GeyserModelEngine.getInstance().getModelEntityType(), viewers, modeledEntity.getBase().getLocation());
return entity;
}
@@ -96,30 +69,4 @@ public class ModelEntity {
}
- public void applyFeatures(LivingEntity display, String name) {
- display.setGravity(false);
- display.setMaxHealth(2048);
- display.setHealth(2048);
- display.setMetadata("model_entity", new FixedMetadataValue(GeyserModelEngine.getInstance(), true));
-
- //display.setInvulnerable(true);
-
- display.setAI(false);
- display.setSilent(true);
- display.setPersistent(false);
-
- // armorStand.setVisible(false);
-
- /*
- String uuid = UUID.randomUUID().toString();
- MobDisguise disguise = new MobDisguise(DisguiseType.getType(entity.getType()));
- disguise.setDisguiseName(uuid);
-
- DisguiseAPI.disguiseEntity(display, disguise);
-
- */
-
- }
-
-
}
diff --git a/src/main/java/re/imc/geysermodelengine/packet/EntityDestroyPacket.java b/src/main/java/re/imc/geysermodelengine/packet/EntityDestroyPacket.java
new file mode 100644
index 0000000..de628ec
--- /dev/null
+++ b/src/main/java/re/imc/geysermodelengine/packet/EntityDestroyPacket.java
@@ -0,0 +1,22 @@
+package re.imc.geysermodelengine.packet;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+
+import java.util.Collections;
+
+public class EntityDestroyPacket implements WrapperPacket {
+
+ private final int id;
+
+ public EntityDestroyPacket(int id) {
+ this.id = id;
+ }
+
+ @Override
+ public PacketContainer encode() {
+ PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
+ packet.getIntLists().write(0, Collections.singletonList(this.id));
+ return packet;
+ }
+}
diff --git a/src/main/java/re/imc/geysermodelengine/packet/EntityHurtAnimationPacket.java b/src/main/java/re/imc/geysermodelengine/packet/EntityHurtAnimationPacket.java
new file mode 100644
index 0000000..975c445
--- /dev/null
+++ b/src/main/java/re/imc/geysermodelengine/packet/EntityHurtAnimationPacket.java
@@ -0,0 +1,21 @@
+package re.imc.geysermodelengine.packet;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+
+public class EntityHurtAnimationPacket implements WrapperPacket {
+
+ private final int id;
+
+ public EntityHurtAnimationPacket(int id) {
+ this.id = id;
+ }
+
+ @Override
+ public PacketContainer encode() {
+ PacketContainer packet = new PacketContainer(PacketType.Play.Server.HURT_ANIMATION);
+ packet.getIntegers().write(0, id);
+ packet.getFloat().write(0, 1f);
+ return packet;
+ }
+}
diff --git a/src/main/java/re/imc/geysermodelengine/packet/EntityMetadataPacket.java b/src/main/java/re/imc/geysermodelengine/packet/EntityMetadataPacket.java
new file mode 100644
index 0000000..edc32d6
--- /dev/null
+++ b/src/main/java/re/imc/geysermodelengine/packet/EntityMetadataPacket.java
@@ -0,0 +1,22 @@
+package re.imc.geysermodelengine.packet;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.wrappers.WrappedDataWatcher;
+
+public class EntityMetadataPacket implements WrapperPacket {
+ private final int id;
+
+ public EntityMetadataPacket(int id) {
+ this.id = id;
+ }
+
+ @Override
+ public PacketContainer encode() {
+ PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
+ packet.getIntegers().write(0, id);
+ WrappedDataWatcher watcher = new WrappedDataWatcher();
+ packet.getWatchableCollectionModifier().writeSafely(0, watcher.getWatchableObjects());
+ return packet;
+ }
+}
diff --git a/src/main/java/re/imc/geysermodelengine/packet/EntitySpawnPacket.java b/src/main/java/re/imc/geysermodelengine/packet/EntitySpawnPacket.java
new file mode 100644
index 0000000..7dea6c5
--- /dev/null
+++ b/src/main/java/re/imc/geysermodelengine/packet/EntitySpawnPacket.java
@@ -0,0 +1,44 @@
+package re.imc.geysermodelengine.packet;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.ProtocolLibrary;
+import com.comphenix.protocol.events.PacketContainer;
+import org.bukkit.Location;
+import org.bukkit.entity.EntityType;
+
+import java.util.UUID;
+
+public class EntitySpawnPacket implements WrapperPacket {
+
+ private final int id;
+ private final UUID uuid;
+ private final EntityType type;
+ private final Location location;
+ public EntitySpawnPacket(int entityID, UUID uuid, EntityType type, Location location) {
+ this.id = entityID;
+ this.uuid = uuid;
+ this.type = type;
+ this.location = location;
+ }
+
+ @Override
+ public PacketContainer encode() {
+ PacketContainer packet = ProtocolLibrary.getProtocolManager()
+ .createPacket(PacketType.Play.Server.SPAWN_ENTITY);
+ packet.getIntegers()
+ .write(0, this.id);
+ packet.getUUIDs()
+ .write(0, this.uuid);
+ packet.getDoubles()
+ .write(0, this.location.getX())
+ .write(1, this.location.getY())
+ .write(2, this.location.getZ());
+ packet.getBytes()
+ .write(0, (byte) (this.location.getYaw() * 256.0F / 360.0F))
+ .write(1, (byte) (this.location.getPitch() * 256.0F / 360.0F));
+ packet.getEntityTypeModifier()
+ .writeSafely(0, type);
+
+ return packet;
+ }
+}
diff --git a/src/main/java/re/imc/geysermodelengine/packet/EntityTeleportPacket.java b/src/main/java/re/imc/geysermodelengine/packet/EntityTeleportPacket.java
new file mode 100644
index 0000000..9dbd221
--- /dev/null
+++ b/src/main/java/re/imc/geysermodelengine/packet/EntityTeleportPacket.java
@@ -0,0 +1,27 @@
+package re.imc.geysermodelengine.packet;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+import org.bukkit.Location;
+
+public class EntityTeleportPacket implements WrapperPacket {
+
+ private final int id;
+ private final Location loc;
+
+ public EntityTeleportPacket(int entityID, Location location) {
+ this.id = entityID;
+ this.loc = location;
+ }
+ @Override
+ public PacketContainer encode() {
+ PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
+ packet.getIntegers().write(0, this.id);
+ packet.getDoubles().write(0, loc.getX());
+ packet.getDoubles().write(1, loc.getY());
+ packet.getDoubles().write(2, loc.getZ());
+ packet.getBytes().write(1, (byte) (loc.getPitch() * 256.0F / 360.0F));
+ packet.getBytes().write(0, (byte) (loc.getYaw() * 256.0F / 360.0F));
+ return packet;
+ }
+}
diff --git a/src/main/java/re/imc/geysermodelengine/packet/WrapperPacket.java b/src/main/java/re/imc/geysermodelengine/packet/WrapperPacket.java
new file mode 100644
index 0000000..1ccb3a1
--- /dev/null
+++ b/src/main/java/re/imc/geysermodelengine/packet/WrapperPacket.java
@@ -0,0 +1,9 @@
+package re.imc.geysermodelengine.packet;
+
+import com.comphenix.protocol.events.PacketContainer;
+
+public interface WrapperPacket {
+
+ default WrapperPacket decode() { return null; };
+ default PacketContainer encode() { return null; };
+}
diff --git a/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java b/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java
new file mode 100644
index 0000000..c355ecd
--- /dev/null
+++ b/src/main/java/re/imc/geysermodelengine/packet/entity/PacketEntity.java
@@ -0,0 +1,803 @@
+package re.imc.geysermodelengine.packet.entity;
+
+import com.comphenix.protocol.ProtocolLibrary;
+import io.papermc.paper.entity.TeleportFlag;
+import io.papermc.paper.threadedregions.scheduler.EntityScheduler;
+import net.kyori.adventure.text.Component;
+import org.bukkit.*;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.PistonMoveReaction;
+import org.bukkit.entity.*;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+import org.bukkit.metadata.MetadataValue;
+import org.bukkit.permissions.Permission;
+import org.bukkit.permissions.PermissionAttachment;
+import org.bukkit.permissions.PermissionAttachmentInfo;
+import org.bukkit.persistence.PersistentDataContainer;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.util.BoundingBox;
+import org.bukkit.util.Vector;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import re.imc.geysermodelengine.packet.*;
+
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class PacketEntity implements Entity {
+ public PacketEntity(EntityType type, Set viewers, Location location) {
+ this.id = ThreadLocalRandom.current().nextInt(20000, 100000000);
+ this.uuid = UUID.randomUUID();
+ this.type = type;
+ this.viewers = viewers;
+ this.location = location;
+ }
+
+ private int id;
+ private UUID uuid;
+ private EntityType type;
+ private Set viewers;
+ private Location location;
+ private boolean removed = false;
+ @Override
+ public @NotNull Location getLocation() {
+ return location;
+ }
+
+ @Override
+ public boolean teleport(@NotNull Location location) {
+ this.location = location.clone();
+ sendLocationPacket(viewers);
+ return true;
+ }
+
+
+
+ @Override
+ public void remove() {
+ removed = true;
+ sendEntityDestroyPacket(viewers);
+ }
+
+ @Override
+ public boolean isDead() {
+ return removed;
+ }
+
+ @Override
+ public boolean isValid() {
+ return !removed;
+ }
+
+ public void sendSpawnPacket(Collection players) {
+ EntitySpawnPacket packet = new EntitySpawnPacket(id, uuid, type, location);
+ EntityMetadataPacket metadataPacket = new EntityMetadataPacket(id);
+ players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode()));
+ players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, metadataPacket.encode()));
+ }
+ public void sendLocationPacket(Collection players) {
+ EntityTeleportPacket packet = new EntityTeleportPacket(id, location);
+ players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode()));
+
+ }
+
+ public void sendHurtPacket(Collection players) {
+ EntityHurtAnimationPacket packet = new EntityHurtAnimationPacket(id);
+ players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode()));
+ }
+
+ public void sendEntityDestroyPacket(Collection players) {
+ EntityDestroyPacket packet = new EntityDestroyPacket(id);
+ players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode()));
+ }
+
+ @Override
+ public int getEntityId() {
+ return id;
+ }
+
+ // ----------------
+
+ @Override
+ public @Nullable Location getLocation(@Nullable Location location) {
+ return null;
+ }
+
+ @Override
+ public void setVelocity(@NotNull Vector vector) {
+
+ }
+
+ @Override
+ public @NotNull Vector getVelocity() {
+ return null;
+ }
+
+ @Override
+ public double getHeight() {
+ return 0;
+ }
+
+ @Override
+ public double getWidth() {
+ return 0;
+ }
+
+ @Override
+ public @NotNull BoundingBox getBoundingBox() {
+ return null;
+ }
+
+ @Override
+ public boolean isOnGround() {
+ return false;
+ }
+
+ @Override
+ public boolean isInWater() {
+ return false;
+ }
+
+ @Override
+ public @NotNull World getWorld() {
+ return null;
+ }
+
+ @Override
+ public void setRotation(float v, float v1) {
+
+ }
+
+ @Override
+ public boolean teleport(@NotNull Location location, PlayerTeleportEvent.@NotNull TeleportCause teleportCause, @NotNull TeleportFlag @NotNull ... teleportFlags) {
+ return false;
+ }
+
+
+
+ @Override
+ public boolean teleport(@NotNull Location location, PlayerTeleportEvent.@NotNull TeleportCause teleportCause) {
+ return false;
+ }
+
+ @Override
+ public boolean teleport(@NotNull Entity entity) {
+ return false;
+ }
+
+ @Override
+ public boolean teleport(@NotNull Entity entity, PlayerTeleportEvent.@NotNull TeleportCause teleportCause) {
+ return false;
+ }
+
+ @Override
+ public @NotNull CompletableFuture teleportAsync(@NotNull Location location, PlayerTeleportEvent.@NotNull TeleportCause teleportCause, @NotNull TeleportFlag @NotNull ... teleportFlags) {
+ return null;
+ }
+
+ @Override
+ public @NotNull List getNearbyEntities(double v, double v1, double v2) {
+ return null;
+ }
+
+
+
+ @Override
+ public int getFireTicks() {
+ return 0;
+ }
+
+ @Override
+ public int getMaxFireTicks() {
+ return 0;
+ }
+
+ @Override
+ public void setFireTicks(int i) {
+
+ }
+
+ @Override
+ public void setVisualFire(boolean b) {
+
+ }
+
+ @Override
+ public boolean isVisualFire() {
+ return false;
+ }
+
+ @Override
+ public int getFreezeTicks() {
+ return 0;
+ }
+
+ @Override
+ public int getMaxFreezeTicks() {
+ return 0;
+ }
+
+ @Override
+ public void setFreezeTicks(int i) {
+
+ }
+
+ @Override
+ public boolean isFrozen() {
+ return false;
+ }
+
+ @Override
+ public void setInvisible(boolean b) {
+
+ }
+
+ @Override
+ public boolean isInvisible() {
+ return false;
+ }
+
+ @Override
+ public void setNoPhysics(boolean b) {
+
+ }
+
+ @Override
+ public boolean hasNoPhysics() {
+ return false;
+ }
+
+ @Override
+ public boolean isFreezeTickingLocked() {
+ return false;
+ }
+
+ @Override
+ public void lockFreezeTicks(boolean b) {
+
+ }
+
+
+ @Override
+ public void sendMessage(@NotNull String s) {
+
+ }
+
+ @Override
+ public void sendMessage(@NotNull String... strings) {
+
+ }
+
+ @Override
+ public void sendMessage(@Nullable UUID uuid, @NotNull String s) {
+
+ }
+
+ @Override
+ public void sendMessage(@Nullable UUID uuid, @NotNull String... strings) {
+
+ }
+
+ @Override
+ public @NotNull Server getServer() {
+ return null;
+ }
+
+ @Override
+ public @NotNull String getName() {
+ return null;
+ }
+
+ @Override
+ public boolean isPersistent() {
+ return false;
+ }
+
+ @Override
+ public void setPersistent(boolean b) {
+
+ }
+
+ @Override
+ public @Nullable Entity getPassenger() {
+ return null;
+ }
+
+ @Override
+ public boolean setPassenger(@NotNull Entity entity) {
+ return false;
+ }
+
+ @Override
+ public @NotNull List getPassengers() {
+ return null;
+ }
+
+ @Override
+ public boolean addPassenger(@NotNull Entity entity) {
+ return false;
+ }
+
+ @Override
+ public boolean removePassenger(@NotNull Entity entity) {
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public boolean eject() {
+ return false;
+ }
+
+ @Override
+ public float getFallDistance() {
+ return 0;
+ }
+
+ @Override
+ public void setFallDistance(float v) {
+
+ }
+
+ @Override
+ public void setLastDamageCause(@Nullable EntityDamageEvent entityDamageEvent) {
+
+ }
+
+ @Override
+ public @Nullable EntityDamageEvent getLastDamageCause() {
+ return null;
+ }
+
+ @Override
+ public @NotNull UUID getUniqueId() {
+ return null;
+ }
+
+ @Override
+ public int getTicksLived() {
+ return 0;
+ }
+
+ @Override
+ public void setTicksLived(int i) {
+
+ }
+
+ @Override
+ public void playEffect(@NotNull EntityEffect entityEffect) {
+
+ }
+
+ @Override
+ public @NotNull EntityType getType() {
+ return null;
+ }
+
+ @Override
+ public @NotNull Sound getSwimSound() {
+ return null;
+ }
+
+ @Override
+ public @NotNull Sound getSwimSplashSound() {
+ return null;
+ }
+
+ @Override
+ public @NotNull Sound getSwimHighSpeedSplashSound() {
+ return null;
+ }
+
+ @Override
+ public boolean isInsideVehicle() {
+ return false;
+ }
+
+ @Override
+ public boolean leaveVehicle() {
+ return false;
+ }
+
+ @Override
+ public @Nullable Entity getVehicle() {
+ return null;
+ }
+
+ @Override
+ public void setCustomNameVisible(boolean b) {
+
+ }
+
+ @Override
+ public boolean isCustomNameVisible() {
+ return false;
+ }
+
+ @Override
+ public void setVisibleByDefault(boolean b) {
+
+ }
+
+ @Override
+ public boolean isVisibleByDefault() {
+ return false;
+ }
+
+ @Override
+ public @NotNull Set getTrackedBy() {
+ return null;
+ }
+
+ @Override
+ public void setGlowing(boolean b) {
+
+ }
+
+ @Override
+ public boolean isGlowing() {
+ return false;
+ }
+
+ @Override
+ public void setInvulnerable(boolean b) {
+
+ }
+
+ @Override
+ public boolean isInvulnerable() {
+ return false;
+ }
+
+ @Override
+ public boolean isSilent() {
+ return false;
+ }
+
+ @Override
+ public void setSilent(boolean b) {
+
+ }
+
+ @Override
+ public boolean hasGravity() {
+ return false;
+ }
+
+ @Override
+ public void setGravity(boolean b) {
+
+ }
+
+ @Override
+ public int getPortalCooldown() {
+ return 0;
+ }
+
+ @Override
+ public void setPortalCooldown(int i) {
+
+ }
+
+ @Override
+ public @NotNull Set getScoreboardTags() {
+ return null;
+ }
+
+ @Override
+ public boolean addScoreboardTag(@NotNull String s) {
+ return false;
+ }
+
+ @Override
+ public boolean removeScoreboardTag(@NotNull String s) {
+ return false;
+ }
+
+ @Override
+ public @NotNull PistonMoveReaction getPistonMoveReaction() {
+ return null;
+ }
+
+ @Override
+ public @NotNull BlockFace getFacing() {
+ return null;
+ }
+
+ @Override
+ public @NotNull Pose getPose() {
+ return null;
+ }
+
+ @Override
+ public boolean isSneaking() {
+ return false;
+ }
+
+ @Override
+ public void setSneaking(boolean b) {
+
+ }
+
+ @Override
+ public void setPose(@NotNull Pose pose, boolean b) {
+
+ }
+
+ @Override
+ public boolean hasFixedPose() {
+ return false;
+ }
+
+ @Override
+ public @NotNull SpawnCategory getSpawnCategory() {
+ return null;
+ }
+
+ @Override
+ public boolean isInWorld() {
+ return false;
+ }
+
+ @Override
+ public @Nullable EntitySnapshot createSnapshot() {
+ return null;
+ }
+
+ @Override
+ public @NotNull Entity copy() {
+ return null;
+ }
+
+ @Override
+ public @NotNull Entity copy(@NotNull Location location) {
+ return null;
+ }
+
+ @Override
+ public @NotNull Spigot spigot() {
+ return null;
+ }
+
+ @Override
+ public @NotNull Component name() {
+ return null;
+ }
+
+ @Override
+ public @NotNull Component teamDisplayName() {
+ return null;
+ }
+
+ @Override
+ public @Nullable Location getOrigin() {
+ return null;
+ }
+
+ @Override
+ public boolean fromMobSpawner() {
+ return false;
+ }
+
+ @Override
+ public CreatureSpawnEvent.@NotNull SpawnReason getEntitySpawnReason() {
+ return null;
+ }
+
+ @Override
+ public boolean isUnderWater() {
+ return false;
+ }
+
+ @Override
+ public boolean isInRain() {
+ return false;
+ }
+
+ @Override
+ public boolean isInBubbleColumn() {
+ return false;
+ }
+
+ @Override
+ public boolean isInWaterOrRain() {
+ return false;
+ }
+
+ @Override
+ public boolean isInWaterOrBubbleColumn() {
+ return false;
+ }
+
+ @Override
+ public boolean isInWaterOrRainOrBubbleColumn() {
+ return false;
+ }
+
+ @Override
+ public boolean isInLava() {
+ return false;
+ }
+
+ @Override
+ public boolean isTicking() {
+ return false;
+ }
+
+ @Override
+ public @NotNull Set getTrackedPlayers() {
+ return null;
+ }
+
+ @Override
+ public boolean spawnAt(@NotNull Location location, CreatureSpawnEvent.@NotNull SpawnReason spawnReason) {
+ return false;
+ }
+
+ @Override
+ public boolean isInPowderedSnow() {
+ return false;
+ }
+
+ @Override
+ public double getX() {
+ return 0;
+ }
+
+ @Override
+ public double getY() {
+ return 0;
+ }
+
+ @Override
+ public double getZ() {
+ return 0;
+ }
+
+ @Override
+ public float getPitch() {
+ return 0;
+ }
+
+ @Override
+ public float getYaw() {
+ return 0;
+ }
+
+ @Override
+ public boolean collidesAt(@NotNull Location location) {
+ return false;
+ }
+
+ @Override
+ public boolean wouldCollideUsing(@NotNull BoundingBox boundingBox) {
+ return false;
+ }
+
+ @Override
+ public @NotNull EntityScheduler getScheduler() {
+ return null;
+ }
+
+ @Override
+ public @NotNull String getScoreboardEntryName() {
+ return null;
+ }
+
+ @Override
+ public @Nullable Component customName() {
+ return null;
+ }
+
+ @Override
+ public void customName(@Nullable Component component) {
+
+ }
+
+ @Override
+ public @Nullable String getCustomName() {
+ return null;
+ }
+
+ @Override
+ public void setCustomName(@Nullable String s) {
+
+ }
+
+ @Override
+ public void setMetadata(@NotNull String s, @NotNull MetadataValue metadataValue) {
+
+ }
+
+ @Override
+ public @NotNull List getMetadata(@NotNull String s) {
+ return null;
+ }
+
+ @Override
+ public boolean hasMetadata(@NotNull String s) {
+ return false;
+ }
+
+ @Override
+ public void removeMetadata(@NotNull String s, @NotNull Plugin plugin) {
+
+ }
+
+ @Override
+ public boolean isPermissionSet(@NotNull String s) {
+ return false;
+ }
+
+ @Override
+ public boolean isPermissionSet(@NotNull Permission permission) {
+ return false;
+ }
+
+ @Override
+ public boolean hasPermission(@NotNull String s) {
+ return false;
+ }
+
+ @Override
+ public boolean hasPermission(@NotNull Permission permission) {
+ return false;
+ }
+
+ @Override
+ public @NotNull PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String s, boolean b) {
+ return null;
+ }
+
+ @Override
+ public @NotNull PermissionAttachment addAttachment(@NotNull Plugin plugin) {
+ return null;
+ }
+
+ @Override
+ public @Nullable PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String s, boolean b, int i) {
+ return null;
+ }
+
+ @Override
+ public @Nullable PermissionAttachment addAttachment(@NotNull Plugin plugin, int i) {
+ return null;
+ }
+
+ @Override
+ public void removeAttachment(@NotNull PermissionAttachment permissionAttachment) {
+
+ }
+
+ @Override
+ public void recalculatePermissions() {
+
+ }
+
+ @Override
+ public @NotNull Set getEffectivePermissions() {
+ return null;
+ }
+
+ @Override
+ public boolean isOp() {
+ return false;
+ }
+
+ @Override
+ public void setOp(boolean b) {
+
+ }
+
+ @Override
+ public @NotNull PersistentDataContainer getPersistentDataContainer() {
+ return null;
+ }
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index eee40f1..bf38848 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -1,5 +1,5 @@
-skin-send-delay: 0
-skin-view-distance: 50
+data-send-delay: 5
+entity-view-distance: 50
join-send-delay: 20
model-entity-type: BAT # must be a living entity
debug: false
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index c7c9df6..5c607b9 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,6 +1,9 @@
name: GeyserModelEngine
version: '${project.version}'
main: re.imc.geysermodelengine.GeyserModelEngine
+authors:
+ - zimzaza4
+ - willem.dev
api-version: '1.19'
depend:
- ModelEngine