mirror of
https://github.com/GeyserExtensionists/GeyserModelEngine.git
synced 2025-12-19 15:09:18 +00:00
Major changes alongside PacketEvents API updated for 1.21.11
This commit is contained in:
61
paper/build.gradle.kts
Normal file
61
paper/build.gradle.kts
Normal file
@@ -0,0 +1,61 @@
|
||||
plugins {
|
||||
id("java")
|
||||
id("com.gradleup.shadow") version "9.2.2"
|
||||
}
|
||||
|
||||
group = "re.imc"
|
||||
version = "1.0.0"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
maven("https://central.sonatype.com/repository/maven-snapshots/")
|
||||
|
||||
maven("https://mvn.lumine.io/repository/maven-public/")
|
||||
|
||||
maven("https://repo.opencollab.dev/main/")
|
||||
|
||||
maven("https://repo.codemc.io/repository/maven-public/")
|
||||
maven("https://repo.codemc.io/repository/maven-releases/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
|
||||
// implementation("dev.jorel:commandapi-paper-shade:11.0.0")
|
||||
|
||||
compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.9")
|
||||
compileOnly("io.github.toxicity188:bettermodel:1.14.0")
|
||||
|
||||
compileOnly(files("libs/geyserutils-spigot-1.0-SNAPSHOT.jar"))
|
||||
compileOnly("org.geysermc.floodgate:api:2.2.4-SNAPSHOT")
|
||||
|
||||
implementation("com.github.retrooper:packetevents-spigot:2.11.0")
|
||||
implementation("org.bstats:bstats-bukkit:3.0.2")
|
||||
|
||||
implementation("org.reflections:reflections:0.10.2")
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
tasks.shadowJar {
|
||||
archiveFileName.set("${rootProject.name}-${version}.jar")
|
||||
|
||||
relocate("dev.jorel.commandapi", "re.imc.geysermodelengine.libs.commandapi")
|
||||
|
||||
relocate("com.github.retrooper", "re.imc.geysermodelengine.libs.com.github.retrooper.packetevents")
|
||||
relocate("io.github.retrooper", "re.imc.geysermodelengine.libs.io.github.retrooper.packetevents")
|
||||
|
||||
relocate("org.bstats", "re.imc.geysermodelengine.libs.bstats")
|
||||
|
||||
relocate("org.reflections", "re.imc.geysermodelengine.libs.reflections")
|
||||
}
|
||||
|
||||
tasks.build {
|
||||
dependsOn("shadowJar")
|
||||
}
|
||||
BIN
paper/libs/geyserutils-spigot-1.0-SNAPSHOT.jar
Normal file
BIN
paper/libs/geyserutils-spigot-1.0-SNAPSHOT.jar
Normal file
Binary file not shown.
@@ -0,0 +1,104 @@
|
||||
package re.imc.geysermodelengine;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
||||
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import re.imc.geysermodelengine.listener.ModelListener;
|
||||
import re.imc.geysermodelengine.listener.MountPacketListener;
|
||||
import re.imc.geysermodelengine.managers.ConfigManager;
|
||||
import re.imc.geysermodelengine.managers.commands.CommandManager;
|
||||
import re.imc.geysermodelengine.managers.model.EntityTaskManager;
|
||||
import re.imc.geysermodelengine.managers.model.ModelManager;
|
||||
import re.imc.geysermodelengine.runnables.BedrockMountControlRunnable;
|
||||
import re.imc.geysermodelengine.runnables.UpdateTaskRunnable;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class GeyserModelEngine extends JavaPlugin {
|
||||
|
||||
private ConfigManager configManager;
|
||||
|
||||
private CommandManager commandManager;
|
||||
|
||||
private ModelManager modelManager;
|
||||
private EntityTaskManager entityTaskManager;
|
||||
|
||||
private ScheduledExecutorService schedulerPool;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
||||
PacketEvents.getAPI().load();
|
||||
|
||||
// CommandAPI.onLoad(new CommandAPIPaperConfig(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
loadHooks();
|
||||
loadManagers();
|
||||
loadRunnables();
|
||||
|
||||
loadBStats();
|
||||
|
||||
PacketEvents.getAPI().getEventManager().registerListener(new MountPacketListener(this), PacketListenerPriority.NORMAL);
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(new ModelListener(this), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
this.modelManager.removeEntities();
|
||||
|
||||
PacketEvents.getAPI().terminate();
|
||||
// CommandAPI.onDisable();
|
||||
}
|
||||
|
||||
private void loadHooks() {
|
||||
PacketEvents.getAPI().init();
|
||||
// CommandAPI.onEnable();
|
||||
}
|
||||
|
||||
private void loadBStats() {
|
||||
if (configManager.getConfig().getBoolean("metrics.bstats", true)) new Metrics(this, 26981);
|
||||
}
|
||||
|
||||
private void loadManagers() {
|
||||
this.configManager = new ConfigManager(this);
|
||||
|
||||
this.commandManager = new CommandManager(this);
|
||||
|
||||
this.modelManager = new ModelManager(this);
|
||||
this.entityTaskManager = new EntityTaskManager(this);
|
||||
}
|
||||
|
||||
private void loadRunnables() {
|
||||
this.schedulerPool = Executors.newScheduledThreadPool(configManager.getConfig().getInt("models.thread-pool-size", 4));
|
||||
|
||||
schedulerPool.scheduleAtFixedRate(new UpdateTaskRunnable(this), 10, configManager.getConfig().getLong("models.entity-position-update-period", 35), TimeUnit.MILLISECONDS);
|
||||
schedulerPool.scheduleAtFixedRate(new BedrockMountControlRunnable(this), 1, 1, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public ConfigManager getConfigManager() {
|
||||
return configManager;
|
||||
}
|
||||
|
||||
public CommandManager getCommandManager() {
|
||||
return commandManager;
|
||||
}
|
||||
|
||||
public ModelManager getModelManager() {
|
||||
return modelManager;
|
||||
}
|
||||
|
||||
public EntityTaskManager getEntityTaskManager() {
|
||||
return entityTaskManager;
|
||||
}
|
||||
|
||||
public ScheduledExecutorService getSchedulerPool() {
|
||||
return schedulerPool;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package re.imc.geysermodelengine.commands.geysermodelenginecommands;
|
||||
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
import re.imc.geysermodelengine.managers.commands.subcommands.SubCommands;
|
||||
import re.imc.geysermodelengine.util.ColourUtils;
|
||||
|
||||
public class GeyserModelEngineReloadCommand implements SubCommands {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
private final ColourUtils colourUtils = new ColourUtils();
|
||||
|
||||
public GeyserModelEngineReloadCommand(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public CommandAPICommand onCommand() {
|
||||
// return new CommandAPICommand("reload")
|
||||
// .withPermission("geysermodelengine.commands.reload")
|
||||
// .executes((sender, args) -> {
|
||||
// Bukkit.getAsyncScheduler().runNow(plugin, scheduledTask -> plugin.getConfigManager().load());
|
||||
// sender.sendMessage(colourUtils.miniFormat(plugin.getConfigManager().getLang().getString("commands.reload.successfully-reloaded")));
|
||||
// });
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package re.imc.geysermodelengine.listener;
|
||||
|
||||
import kr.toxicity.model.api.event.CreateEntityTrackerEvent;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
import re.imc.geysermodelengine.managers.model.entity.BetterModelEntityData;
|
||||
import re.imc.geysermodelengine.managers.model.model.Model;
|
||||
|
||||
public class BetterModelListener implements Listener {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
public BetterModelListener(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onModelSpawn(CreateEntityTrackerEvent event) {
|
||||
plugin.getModelManager().getModelHandler().createModel(event.sourceEntity(), event.getTracker(), event.tracker());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onModelDamage(EntityDamageByEntityEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
|
||||
Model model = plugin.getModelManager().getModelEntitiesCache().get(entity.getEntityId());
|
||||
if (model == null) return;
|
||||
|
||||
BetterModelEntityData entityData = (BetterModelEntityData) model.getEntityData();
|
||||
|
||||
entityData.setHurt(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package re.imc.geysermodelengine.listener;
|
||||
|
||||
import com.ticxo.modelengine.api.events.*;
|
||||
import com.ticxo.modelengine.api.model.ActiveModel;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
import re.imc.geysermodelengine.managers.model.entity.EntityData;
|
||||
import re.imc.geysermodelengine.managers.model.model.Model;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ModelEngineListener implements Listener {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
public ModelEngineListener(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onAddModel(AddModelEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
plugin.getModelManager().getModelHandler().createModel(event.getTarget(), event.getModel());
|
||||
}
|
||||
|
||||
// Needs Testing
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onModelMount(ModelMountEvent event) {
|
||||
if (!event.isDriver()) return;
|
||||
|
||||
ActiveModel activeModel = event.getVehicle();
|
||||
if (activeModel == null) return;
|
||||
|
||||
int entityID = activeModel.getModeledEntity().getBase().getEntityId();
|
||||
|
||||
Map<Model, EntityData> entityDataCache = plugin.getModelManager().getEntitiesCache().get(entityID);
|
||||
if (entityDataCache == null) return;
|
||||
|
||||
Model model = plugin.getModelManager().getModelEntitiesCache().get(entityID);
|
||||
|
||||
EntityData entityData = entityDataCache.get(model);
|
||||
|
||||
if (entityData != null && event.getPassenger() instanceof Player player) {
|
||||
plugin.getModelManager().getDriversCache().put(player.getUniqueId(), Pair.of(event.getVehicle(), event.getSeat()));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onModelDismount(ModelDismountEvent event) {
|
||||
if (event.getPassenger() instanceof Player player) {
|
||||
plugin.getModelManager().getDriversCache().remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package re.imc.geysermodelengine.listener;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
import re.imc.geysermodelengine.util.BedrockUtils;
|
||||
|
||||
public class ModelListener implements Listener {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
public ModelListener(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/*
|
||||
/ xSquishyLiam:
|
||||
/ May change this into a better system?
|
||||
*/
|
||||
@EventHandler
|
||||
public void onWorldInit(WorldInitEvent event) {
|
||||
World world = event.getWorld();
|
||||
world.getEntities().forEach(entity -> plugin.getModelManager().getModelHandler().processEntities(entity));
|
||||
}
|
||||
|
||||
/*
|
||||
/ xSquishyLiam:
|
||||
/ 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) {
|
||||
Player player = event.getPlayer();
|
||||
if (!BedrockUtils.isBedrockPlayer(player)) return;
|
||||
Bukkit.getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> plugin.getModelManager().getPlayerJoinedCache().add(player.getUniqueId()), 10);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (!BedrockUtils.isBedrockPlayer(player)) return;
|
||||
plugin.getModelManager().getPlayerJoinedCache().remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package re.imc.geysermodelengine.listener;
|
||||
|
||||
import com.github.retrooper.packetevents.event.PacketListener;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;
|
||||
import com.ticxo.modelengine.api.ModelEngineAPI;
|
||||
import com.ticxo.modelengine.api.model.ActiveModel;
|
||||
import com.ticxo.modelengine.api.model.bone.type.Mount;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
import re.imc.geysermodelengine.util.BedrockUtils;
|
||||
|
||||
public class MountPacketListener implements PacketListener {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
public MountPacketListener(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() != PacketType.Play.Client.ENTITY_ACTION) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (!BedrockUtils.isBedrockPlayer(player)) return;
|
||||
|
||||
WrapperPlayClientEntityAction action = new WrapperPlayClientEntityAction(event);
|
||||
Pair<ActiveModel, Mount> seat = plugin.getModelManager().getDriversCache().get(player.getUniqueId());
|
||||
|
||||
if (seat == null) return;
|
||||
if (action.getAction() != WrapperPlayClientEntityAction.Action.START_SNEAKING) return;
|
||||
|
||||
ModelEngineAPI.getMountPairManager().tryDismount(player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package re.imc.geysermodelengine.managers;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ConfigManager {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
private FileConfiguration config, lang;
|
||||
|
||||
public ConfigManager(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
load();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (!plugin.getDataFolder().exists()) {
|
||||
plugin.getDataFolder().mkdir();
|
||||
plugin.saveResource("config.yml", false);
|
||||
plugin.saveResource("Lang/messages.yml", false);
|
||||
}
|
||||
|
||||
this.config = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "config.yml"));
|
||||
this.lang = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "Lang/messages.yml"));
|
||||
}
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public FileConfiguration getLang() {
|
||||
return lang;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package re.imc.geysermodelengine.managers.commands;
|
||||
|
||||
import org.reflections.Reflections;
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class CommandManager {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
private final HashMap<String, CommandManagers> commandManagersCache = new HashMap<>();
|
||||
|
||||
public CommandManager(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
load("re.imc.geysermodelengine.managers.commands.managers");
|
||||
}
|
||||
|
||||
private void load(String path) {
|
||||
for (Class<?> clazz : new Reflections(path).getSubTypesOf(CommandManagers.class)) {
|
||||
try {
|
||||
CommandManagers commandManager = (CommandManagers) clazz.getDeclaredConstructor(GeyserModelEngine.class).newInstance(plugin);
|
||||
plugin.getLogger().info("Loading Command Manager - " + commandManager.getName());
|
||||
commandManagersCache.put(commandManager.getName(), commandManager);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException err) {
|
||||
plugin.getLogger().severe("Failed to load Command Manager " + clazz.getName());
|
||||
throw new RuntimeException(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HashMap<String, CommandManagers> getCommandManagersCache() {
|
||||
return commandManagersCache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package re.imc.geysermodelengine.managers.commands;
|
||||
|
||||
import re.imc.geysermodelengine.managers.commands.subcommands.SubCommands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public interface CommandManagers {
|
||||
|
||||
/**
|
||||
* Gets the name of the command manager
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the command manager subcommands
|
||||
*/
|
||||
ArrayList<SubCommands> getCommands();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package re.imc.geysermodelengine.managers.commands.managers.geysermodelengine;
|
||||
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
import re.imc.geysermodelengine.commands.geysermodelenginecommands.GeyserModelEngineReloadCommand;
|
||||
import re.imc.geysermodelengine.managers.commands.CommandManagers;
|
||||
import re.imc.geysermodelengine.managers.commands.subcommands.SubCommands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GeyserModelEngineCommandManager implements CommandManagers {
|
||||
|
||||
private final ArrayList<SubCommands> commands = new ArrayList<>();
|
||||
|
||||
public GeyserModelEngineCommandManager(GeyserModelEngine plugin) {
|
||||
commands.add(new GeyserModelEngineReloadCommand(plugin));
|
||||
|
||||
registerCommand();
|
||||
}
|
||||
|
||||
private void registerCommand() {
|
||||
// CommandAPICommand geyserModelEngineCommand = new CommandAPICommand(getName());
|
||||
//
|
||||
// commands.forEach(subCommands -> geyserModelEngineCommand.withSubcommand(subCommands.onCommand()));
|
||||
//
|
||||
// geyserModelEngineCommand.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "geysermodelengine";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<SubCommands> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package re.imc.geysermodelengine.managers.commands.subcommands;
|
||||
|
||||
public interface SubCommands {
|
||||
|
||||
/**
|
||||
* Subcommand setup
|
||||
*/
|
||||
// CommandAPICommand onCommand();
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package re.imc.geysermodelengine.managers.model;
|
||||
|
||||
import com.ticxo.modelengine.api.animation.BlueprintAnimation;
|
||||
import com.ticxo.modelengine.api.model.ActiveModel;
|
||||
import me.zimzaza4.geyserutils.spigot.api.EntityUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
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.entity.ModelEngineEntityData;
|
||||
import re.imc.geysermodelengine.managers.model.taskshandler.TaskHandler;
|
||||
import re.imc.geysermodelengine.packet.entity.PacketEntity;
|
||||
import re.imc.geysermodelengine.util.BedrockUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class EntityTaskManager {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
private PropertyHandler propertyHandler;
|
||||
|
||||
public EntityTaskManager(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("ModelEngine") != null) {
|
||||
this.propertyHandler = new ModelEnginePropertyHandler(plugin);
|
||||
plugin.getLogger().info("Using ModelEngine property handler!");
|
||||
} else if (Bukkit.getPluginManager().getPlugin("BetterModel") != null) {
|
||||
this.propertyHandler = new BetterModelPropertyHandler(plugin);
|
||||
plugin.getLogger().info("Using BetterModel property handler!");
|
||||
} else {
|
||||
plugin.getLogger().severe("No supported model engine found!");
|
||||
plugin.getServer().getPluginManager().disablePlugin(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkViewers(EntityData model, Set<Player> viewers) {
|
||||
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
|
||||
if (!BedrockUtils.isBedrockPlayer(onlinePlayer)) return;
|
||||
|
||||
if (canSee(onlinePlayer, model.getEntity())) {
|
||||
if (!viewers.contains(onlinePlayer)) {
|
||||
sendSpawnPacket(model, onlinePlayer);
|
||||
viewers.add(onlinePlayer);
|
||||
}
|
||||
} else {
|
||||
if (viewers.contains(onlinePlayer)) {
|
||||
model.getEntity().sendEntityDestroyPacket(Collections.singletonList(onlinePlayer));
|
||||
viewers.remove(onlinePlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendSpawnPacket(EntityData model, Player onlinePlayer) {
|
||||
TaskHandler task = model.getEntityTask();
|
||||
boolean firstJoined = !plugin.getModelManager().getPlayerJoinedCache().contains(onlinePlayer.getUniqueId());
|
||||
|
||||
if (firstJoined) {
|
||||
task.sendEntityData(model, onlinePlayer, plugin.getConfigManager().getConfig().getInt("models.join-send-delay") / 50);
|
||||
} else {
|
||||
task.sendEntityData(model, onlinePlayer, 5);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canSee(Player player, PacketEntity entity) {
|
||||
if (!player.isOnline()) return false;
|
||||
if (!plugin.getModelManager().getPlayerJoinedCache().contains(player.getUniqueId())) return false;
|
||||
|
||||
Location playerLocation = player.getLocation().clone();
|
||||
Location entityLocation = entity.getLocation().clone();
|
||||
playerLocation.setY(0);
|
||||
entityLocation.setY(0);
|
||||
|
||||
if (playerLocation.getWorld() != entityLocation.getWorld()) return false;
|
||||
if (playerLocation.distanceSquared(entityLocation) > player.getSendViewDistance() * player.getSendViewDistance() * 48) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void sendHitBoxToAll(EntityData model) {
|
||||
for (Player viewer : model.getViewers()) {
|
||||
EntityUtils.sendCustomHitBox(viewer, model.getEntity().getEntityId(), 0.01f, 0.01f);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO move this
|
||||
public boolean hasAnimation(ModelEngineEntityData model, String animation) {
|
||||
ActiveModel activeModel = model.getActiveModel();
|
||||
BlueprintAnimation animationProperty = activeModel.getBlueprint().getAnimations().get(animation);
|
||||
return !(animationProperty == null);
|
||||
}
|
||||
|
||||
public PropertyHandler getPropertyHandler() {
|
||||
return propertyHandler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package re.imc.geysermodelengine.managers.model;
|
||||
|
||||
import com.ticxo.modelengine.api.model.ActiveModel;
|
||||
import com.ticxo.modelengine.api.model.bone.type.Mount;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
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 java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ModelManager {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
private ModelHandler modelHandler;
|
||||
|
||||
private final HashSet<UUID> playerJoinedCache = new HashSet<>();
|
||||
|
||||
private final ConcurrentHashMap<Integer, Model> modelEntitiesCache = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<Integer, Map<Model, EntityData>> entitiesCache = new ConcurrentHashMap<>();
|
||||
|
||||
// MEG ONLY
|
||||
private final ConcurrentHashMap<UUID, Pair<ActiveModel, Mount>> driversCache = new ConcurrentHashMap<>();
|
||||
|
||||
public ModelManager(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("ModelEngine") != null) {
|
||||
this.modelHandler = new ModelEngineHandler(plugin);
|
||||
plugin.getLogger().info("Using ModelEngine handler!");
|
||||
} else if (Bukkit.getPluginManager().getPlugin("BetterModel") != null) {
|
||||
this.modelHandler = new BetterModelHandler(plugin);
|
||||
plugin.getLogger().info("Using BetterModel handler!");
|
||||
} else {
|
||||
plugin.getLogger().severe("No supported model engine found!");
|
||||
plugin.getServer().getPluginManager().disablePlugin(plugin);
|
||||
return;
|
||||
}
|
||||
|
||||
modelHandler.loadListeners();
|
||||
}
|
||||
|
||||
public void removeEntities() {
|
||||
for (Map<Model, EntityData> entities : entitiesCache.values()) {
|
||||
entities.forEach((model, modelEntity) -> modelEntity.getEntity().remove());
|
||||
}
|
||||
}
|
||||
|
||||
public ModelHandler getModelHandler() {
|
||||
return modelHandler;
|
||||
}
|
||||
|
||||
public HashSet<UUID> getPlayerJoinedCache() {
|
||||
return playerJoinedCache;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<Integer, Map<Model, EntityData>> getEntitiesCache() {
|
||||
return entitiesCache;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<Integer, Model> getModelEntitiesCache() {
|
||||
return modelEntitiesCache;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<UUID, Pair<ActiveModel, Mount>> getDriversCache() {
|
||||
return driversCache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package re.imc.geysermodelengine.managers.model.entity;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.google.common.collect.Sets;
|
||||
import kr.toxicity.model.api.entity.BaseEntity;
|
||||
import kr.toxicity.model.api.tracker.EntityTracker;
|
||||
import kr.toxicity.model.api.tracker.Tracker;
|
||||
import org.bukkit.Location;
|
||||
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<Player> viewers = Sets.newConcurrentHashSet();
|
||||
|
||||
private final BaseEntity entitySource;
|
||||
private final Tracker tracker;
|
||||
private final EntityTracker entityTracker;
|
||||
|
||||
private BetterModelTaskHandler entityTask;
|
||||
|
||||
private boolean hurt;
|
||||
|
||||
public BetterModelEntityData(GeyserModelEngine plugin, BaseEntity entitySource, Tracker tracker, EntityTracker entityTracker) {
|
||||
this.plugin = plugin;
|
||||
|
||||
this.entitySource = entitySource;
|
||||
this.tracker = tracker;
|
||||
this.entityTracker = entityTracker;
|
||||
this.entity = new PacketEntity(EntityTypes.PIG, viewers, entitySource.location());
|
||||
|
||||
runEntityTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleportToModel() {
|
||||
Location location = entitySource.location();
|
||||
entity.teleport(location);
|
||||
}
|
||||
|
||||
public void runEntityTask() {
|
||||
entityTask = new BetterModelTaskHandler(plugin, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketEntity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Player> getViewers() {
|
||||
return viewers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetterModelTaskHandler getEntityTask() {
|
||||
return entityTask;
|
||||
}
|
||||
|
||||
public void setHurt(boolean hurt) {
|
||||
this.hurt = hurt;
|
||||
}
|
||||
|
||||
public BaseEntity getEntitySource() {
|
||||
return entitySource;
|
||||
}
|
||||
|
||||
public Tracker getTracker() {
|
||||
return tracker;
|
||||
}
|
||||
|
||||
public EntityTracker getEntityTracker() {
|
||||
return entityTracker;
|
||||
}
|
||||
|
||||
public boolean isHurt() {
|
||||
return hurt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package re.imc.geysermodelengine.managers.model.entity;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import re.imc.geysermodelengine.managers.model.taskshandler.TaskHandler;
|
||||
import re.imc.geysermodelengine.packet.entity.PacketEntity;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface EntityData {
|
||||
|
||||
/**
|
||||
* Teleports the packet entity to the model
|
||||
*/
|
||||
void teleportToModel();
|
||||
|
||||
/**
|
||||
* Gets the packet Entity
|
||||
*/
|
||||
PacketEntity getEntity();
|
||||
|
||||
/**
|
||||
* Gets the entity view of players
|
||||
*/
|
||||
Set<Player> getViewers();
|
||||
|
||||
/**
|
||||
* Get the entity task handler
|
||||
*/
|
||||
TaskHandler getEntityTask();
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package re.imc.geysermodelengine.managers.model.entity;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.ticxo.modelengine.api.model.ActiveModel;
|
||||
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.taskshandler.ModelEngineTaskHandler;
|
||||
import re.imc.geysermodelengine.packet.entity.PacketEntity;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ModelEngineEntityData implements EntityData {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
private final PacketEntity entity;
|
||||
private final Set<Player> viewers = Sets.newConcurrentHashSet();
|
||||
|
||||
private final ModeledEntity modeledEntity;
|
||||
private final ActiveModel activeModel;
|
||||
|
||||
private ModelEngineTaskHandler entityTask;
|
||||
|
||||
public ModelEngineEntityData(GeyserModelEngine plugin, ModeledEntity modeledEntity, ActiveModel activeModel) {
|
||||
this.plugin = plugin;
|
||||
|
||||
this.modeledEntity = modeledEntity;
|
||||
this.activeModel = activeModel;
|
||||
this.entity = new PacketEntity(EntityTypes.PIG, viewers, modeledEntity.getBase().getLocation());
|
||||
|
||||
runEntityTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleportToModel() {
|
||||
Location location = modeledEntity.getBase().getLocation();
|
||||
entity.teleport(location);
|
||||
}
|
||||
|
||||
public void runEntityTask() {
|
||||
entityTask = new ModelEngineTaskHandler(plugin, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketEntity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Player> getViewers() {
|
||||
return viewers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelEngineTaskHandler getEntityTask() {
|
||||
return entityTask;
|
||||
}
|
||||
|
||||
public ModeledEntity getModeledEntity() {
|
||||
return modeledEntity;
|
||||
}
|
||||
|
||||
public ActiveModel getActiveModel() {
|
||||
return activeModel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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;
|
||||
|
||||
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 tracker.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelHandler getModelHandler() {
|
||||
return modelHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityData getEntityData() {
|
||||
return entityData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyHandler getPropertyHandler() {
|
||||
return propertyHandler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
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;
|
||||
|
||||
public interface Model {
|
||||
|
||||
/**
|
||||
* Gets the model's name
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the model's entity data
|
||||
*/
|
||||
EntityData getEntityData();
|
||||
|
||||
/**
|
||||
* Gets the model's model handler
|
||||
*/
|
||||
ModelHandler getModelHandler();
|
||||
|
||||
/**
|
||||
* Gets the model's property handler
|
||||
*/
|
||||
PropertyHandler getPropertyHandler();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
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;
|
||||
|
||||
public class ModelEngineModel implements Model {
|
||||
|
||||
private final ActiveModel activeModel;
|
||||
private final ModelHandler modelHandler;
|
||||
private final EntityData entityData;
|
||||
private final PropertyHandler propertyHandler;
|
||||
|
||||
public ModelEngineModel(ActiveModel activeModel, ModelHandler modelHandler, EntityData entityData, PropertyHandler propertyHandler) {
|
||||
this.activeModel = activeModel;
|
||||
this.modelHandler = modelHandler;
|
||||
this.entityData = entityData;
|
||||
this.propertyHandler = propertyHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return activeModel.getBlueprint().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelHandler getModelHandler() {
|
||||
return modelHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityData getEntityData() {
|
||||
return entityData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyHandler getPropertyHandler() {
|
||||
return propertyHandler;
|
||||
}
|
||||
|
||||
public ActiveModel getActiveModel() {
|
||||
return activeModel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package re.imc.geysermodelengine.managers.model.modelhandler;
|
||||
|
||||
import kr.toxicity.model.api.entity.BaseEntity;
|
||||
import kr.toxicity.model.api.tracker.EntityTracker;
|
||||
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;
|
||||
}
|
||||
|
||||
//TODO fix dupe issue - dupe happens when server restart
|
||||
@Override
|
||||
public void createModel(Object... objects) {
|
||||
BaseEntity entitySource = (BaseEntity) objects[0];
|
||||
Tracker tracker = (Tracker) objects[1];
|
||||
EntityTracker entityTracker = (EntityTracker) objects[2];
|
||||
|
||||
int entityID = entitySource.id();
|
||||
|
||||
PropertyHandler propertyHandler = plugin.getEntityTaskManager().getPropertyHandler();
|
||||
EntityData entityData = new BetterModelEntityData(plugin, entitySource, tracker, entityTracker);
|
||||
|
||||
Model model = new BetterModelModel(tracker, this, entityData, propertyHandler);
|
||||
|
||||
Map<Model, EntityData> entityDataCache = plugin.getModelManager().getEntitiesCache().computeIfAbsent(entityID, k -> new HashMap<>());
|
||||
|
||||
for (Map.Entry<Model, EntityData> 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<EntityTrackerRegistry> modeledEntity = BetterModel.registry(entity);
|
||||
//
|
||||
// modeledEntity.ifPresent(m -> createModel(modeledEntity.get().entity(), m.));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadListeners() {
|
||||
Bukkit.getPluginManager().registerEvents(new BetterModelListener(plugin), plugin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
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 org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
import re.imc.geysermodelengine.listener.ModelEngineListener;
|
||||
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 java.util.HashMap;
|
||||
import java.util.Map;
|
||||
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(Object... objects) {
|
||||
ModeledEntity megEntity = (ModeledEntity) objects[0];
|
||||
ActiveModel megActiveModel = (ActiveModel) objects[1];
|
||||
|
||||
int entityID = megEntity.getBase().getEntityId();
|
||||
|
||||
PropertyHandler propertyHandler = plugin.getEntityTaskManager().getPropertyHandler();
|
||||
EntityData entityData = new ModelEngineEntityData(plugin, megEntity, megActiveModel);
|
||||
|
||||
Model model = new ModelEngineModel(megActiveModel, this, entityData, propertyHandler);
|
||||
|
||||
Map<Model, EntityData> entityDataCache = plugin.getModelManager().getEntitiesCache().computeIfAbsent(entityID, k -> new HashMap<>());
|
||||
|
||||
for (Map.Entry<Model, EntityData> entry : entityDataCache.entrySet()) {
|
||||
if (entry.getKey() != model && entry.getKey().getName().equals(megActiveModel.getBlueprint().getName())) {
|
||||
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;
|
||||
|
||||
ModeledEntity modeledEntity = ModelEngineAPI.getModeledEntity(entity);
|
||||
if (modeledEntity == null) return;
|
||||
|
||||
Optional<ActiveModel> model = modeledEntity.getModels().values().stream().findFirst();
|
||||
model.ifPresent(m -> createModel(modeledEntity, m));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadListeners() {
|
||||
Bukkit.getPluginManager().registerEvents(new ModelEngineListener(plugin), plugin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package re.imc.geysermodelengine.managers.model.modelhandler;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public interface ModelHandler {
|
||||
|
||||
/**
|
||||
* Creates the model from the required Model Engine
|
||||
* @param objects Processes the required objects
|
||||
*/
|
||||
void createModel(Object... objects);
|
||||
|
||||
/**
|
||||
* Processes entities into createModel()
|
||||
* @param entity Registers bukkit entities
|
||||
*/
|
||||
void processEntities(Entity entity);
|
||||
|
||||
/**
|
||||
* Loads the required listeners
|
||||
*/
|
||||
void loadListeners();
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Figure out on how to get the scale from BetterModel
|
||||
@Override
|
||||
public void sendScale(EntityData entityData, Collection<Player> players, float lastScale, boolean firstSend) {
|
||||
BetterModelEntityData betterModelEntityData = (BetterModelEntityData) entityData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendColor(EntityData entityData, Collection<Player> players, Color lastColor, boolean firstSend) {
|
||||
if (players.isEmpty()) return;
|
||||
|
||||
BetterModelEntityData betterModelEntityData = (BetterModelEntityData) entityData;
|
||||
|
||||
Color color = new Color(0xFFFFFF);
|
||||
if (betterModelEntityData.isHurt()) color = new Color(betterModelEntityData.getEntityTracker().damageTintValue());
|
||||
|
||||
if (firstSend) {
|
||||
if (color.equals(lastColor)) return;
|
||||
}
|
||||
|
||||
for (Player player : players) {
|
||||
EntityUtils.sendCustomColor(player, betterModelEntityData.getEntity().getEntityId(), color);
|
||||
}
|
||||
|
||||
betterModelEntityData.setHurt(false);
|
||||
}
|
||||
|
||||
@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<Player> players, boolean firstSend, String... forceAnims) {
|
||||
BetterModelEntityData model = (BetterModelEntityData) entityData;
|
||||
|
||||
int entity = model.getEntity().getEntityId();
|
||||
Set<String> forceAnimSet = Set.of(forceAnims);
|
||||
|
||||
Map<String, Boolean> boneUpdates = new HashMap<>();
|
||||
Map<String, Boolean> animUpdates = new HashMap<>();
|
||||
Set<String> 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().animations().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().keySet()) {
|
||||
if (anims.contains(id)) {
|
||||
animUpdates.put(id, true);
|
||||
} else {
|
||||
animUpdates.put(id, false);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> lastPlayed = new HashSet<>(model.getEntityTask().getLastPlayedAnim().asMap().keySet());
|
||||
|
||||
for (Map.Entry<String, Boolean> 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<String, Integer> intUpdates = new HashMap<>();
|
||||
int i = 0;
|
||||
|
||||
for (Integer integer : BooleanPacker.mapBooleansToInts(boneUpdates)) {
|
||||
intUpdates.put(plugin.getConfigManager().getConfig().getString("models.namespace") + ":bone" + i, integer);
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (Integer integer : BooleanPacker.mapBooleansToInts(animUpdates)) {
|
||||
intUpdates.put(plugin.getConfigManager().getConfig().getString("models.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("options.debug")) plugin.getLogger().info(animUpdates.toString());
|
||||
|
||||
List<String> list = new ArrayList<>(boneUpdates.keySet());
|
||||
Collections.sort(list);
|
||||
|
||||
players.forEach(player -> 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<String, Boolean> 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
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.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.util.*;
|
||||
|
||||
public class ModelEnginePropertyHandler implements PropertyHandler {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
public ModelEnginePropertyHandler(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendScale(EntityData modelData, Collection<Player> players, float lastScale, boolean firstSend) {
|
||||
try {
|
||||
if (players.isEmpty()) return;
|
||||
|
||||
ModelEngineEntityData modelEngineEntityData = (ModelEngineEntityData) modelData;
|
||||
|
||||
Vector3fc scale = modelEngineEntityData.getActiveModel().getScale();
|
||||
|
||||
float average = (scale.x() + scale.y() + scale.z()) / 3;
|
||||
|
||||
if (!firstSend) {
|
||||
if (average == lastScale) return;
|
||||
}
|
||||
|
||||
players.forEach(player -> EntityUtils.sendCustomScale(player, modelEngineEntityData.getEntity().getEntityId(), average));
|
||||
} catch (Exception err) {
|
||||
throw new RuntimeException(err);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendColor(EntityData entityData, Collection<Player> players, Color lastColor, boolean firstSend) {
|
||||
if (players.isEmpty()) return;
|
||||
|
||||
ModelEngineEntityData data = (ModelEngineEntityData) entityData;
|
||||
Color color = calculateCurrentColor(data);
|
||||
|
||||
if (!firstSend && color.equals(lastColor)) return;
|
||||
|
||||
players.forEach(player -> EntityUtils.sendCustomColor(player, data.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<Player> players, boolean firstSend, String... forceAnims) {
|
||||
ModelEngineEntityData model = (ModelEngineEntityData) entityData;
|
||||
|
||||
int entity = model.getEntity().getEntityId();
|
||||
Set<String> forceAnimSet = Set.of(forceAnims);
|
||||
|
||||
Map<String, Boolean> boneUpdates = new LinkedHashMap<>();
|
||||
Map<String, Boolean> animUpdates = new HashMap<>();
|
||||
Set<String> anims = new HashSet<>();
|
||||
|
||||
model.getActiveModel().getBlueprint().getBones().forEach((s, bone) -> processBone(model, bone, boneUpdates));
|
||||
|
||||
AnimationHandler handler = model.getActiveModel().getAnimationHandler();
|
||||
Set<String> 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<String> lastPlayed = new HashSet<>(model.getEntityTask().getLastPlayedAnim().asMap().keySet());
|
||||
|
||||
for (Map.Entry<String, Boolean> 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<String, Integer> intUpdates = new HashMap<>();
|
||||
int i = 0;
|
||||
|
||||
for (Integer integer : BooleanPacker.mapBooleansToInts(boneUpdates)) {
|
||||
intUpdates.put(plugin.getConfigManager().getConfig().getString("models.namespace") + ":bone" + i, integer);
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (Integer integer : BooleanPacker.mapBooleansToInts(animUpdates)) {
|
||||
intUpdates.put(plugin.getConfigManager().getConfig().getString("models.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("options.debug")) plugin.getLogger().info(animUpdates.toString());
|
||||
|
||||
players.forEach(player -> EntityUtils.sendIntProperties(player, entity, intUpdates));
|
||||
}
|
||||
|
||||
private void processBone(ModelEngineEntityData model, BlueprintBone bone, Map<String, Boolean> 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;
|
||||
|
||||
bone.getChildren().values().forEach(child -> processBone(model, child, map));
|
||||
|
||||
ModelBone activeBone = model.getActiveModel().getBones().get(bone.getName());
|
||||
|
||||
boolean visible = false;
|
||||
if (activeBone != null) visible = activeBone.isVisible();
|
||||
|
||||
map.put(name, visible);
|
||||
}
|
||||
|
||||
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 Color calculateCurrentColor(ModelEngineEntityData modelEngineEntityData) {
|
||||
if (modelEngineEntityData.getActiveModel().isMarkedHurt()) return new Color(modelEngineEntityData.getActiveModel().getDamageTint().asARGB());
|
||||
return new Color(modelEngineEntityData.getActiveModel().getDefaultTint().asARGB());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
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 {
|
||||
|
||||
/**
|
||||
* Sends scale of the entity to the player
|
||||
* @param entityData The data of the entity
|
||||
* @param players Collection of players from the entity view
|
||||
* @param lastScale Sends the last scale to the player
|
||||
* @param firstSend Checks if it's the first time to send scale to the player
|
||||
*/
|
||||
void sendScale(EntityData entityData, Collection<Player> players, float lastScale, boolean firstSend);
|
||||
|
||||
/**
|
||||
* Sends a colour tint to the player
|
||||
* @param entityData The data of the entity
|
||||
* @param players Collection of players from the entity view
|
||||
* @param lastColor Sends the last colour to the player
|
||||
* @param firstSend Checks if it's the first time to send colour to the player
|
||||
*/
|
||||
void sendColor(EntityData entityData, Collection<Player> players, Color lastColor, boolean firstSend);
|
||||
|
||||
/**
|
||||
* Sends a hitbox to the player
|
||||
* @param entityData The data of the entity
|
||||
* @param player Sends the player the entity hitbox
|
||||
*/
|
||||
void sendHitBox(EntityData entityData, Player player);
|
||||
|
||||
/**
|
||||
* Updates the entity to all viewable players
|
||||
* @param entityData The data of the entity
|
||||
* @param players Collection of players from the entity view
|
||||
* @param firstSend Checks if it's the first time to send the entity to the player
|
||||
* @param forceAnims Forces the entity to do an animation
|
||||
*/
|
||||
void updateEntityProperties(EntityData entityData, Collection<Player> players, boolean firstSend, String... forceAnims);
|
||||
}
|
||||
@@ -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.entity.BaseEntity;
|
||||
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<String, Integer> lastIntSet = new ConcurrentHashMap<>();
|
||||
private final Cache<String, Boolean> 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<Player> viewers = entityData.getViewers();
|
||||
BaseEntity entitySource = entityData.getEntitySource();
|
||||
Tracker tracker = entityData.getTracker();
|
||||
|
||||
entityData.teleportToModel();
|
||||
|
||||
if (entitySource.dead() || tracker.forRemoval()) {
|
||||
removed = true;
|
||||
entity.remove();
|
||||
|
||||
plugin.getModelManager().getEntitiesCache().remove(entitySource.id());
|
||||
plugin.getModelManager().getModelEntitiesCache().remove(entitySource.id());
|
||||
|
||||
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("models.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<String, Integer> getLastIntSet() {
|
||||
return lastIntSet;
|
||||
}
|
||||
|
||||
public Cache<String, Boolean> getLastPlayedAnim() {
|
||||
return lastPlayedAnim;
|
||||
}
|
||||
|
||||
public ScheduledFuture getScheduledFuture() {
|
||||
return scheduledFuture;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
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<String, Integer> lastIntSet = new ConcurrentHashMap<>();
|
||||
private final Cache<String, Boolean> 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() {
|
||||
if (removed || entityData == null) return;
|
||||
|
||||
PacketEntity entity = entityData.getEntity();
|
||||
if (entity == null || entity.isDead()) return;
|
||||
|
||||
plugin.getEntityTaskManager().checkViewers(entityData, entityData.getViewers());
|
||||
|
||||
entityData.teleportToModel();
|
||||
|
||||
Set<Player> 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) {
|
||||
viewers.removeIf(viewer -> !plugin.getEntityTaskManager().canSee(viewer, entityData.getEntity()));
|
||||
}
|
||||
}
|
||||
|
||||
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("models.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<String, Integer> getLastIntSet() {
|
||||
return lastIntSet;
|
||||
}
|
||||
|
||||
public Cache<String, Boolean> getLastPlayedAnim() {
|
||||
return lastPlayedAnim;
|
||||
}
|
||||
|
||||
public ScheduledFuture getScheduledFuture() {
|
||||
return scheduledFuture;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package re.imc.geysermodelengine.managers.model.taskshandler;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import re.imc.geysermodelengine.managers.model.entity.EntityData;
|
||||
|
||||
public interface TaskHandler {
|
||||
|
||||
/**
|
||||
* Runs the entity scheduler
|
||||
*/
|
||||
void runAsync();
|
||||
|
||||
/**
|
||||
* Spawns the entity to the player
|
||||
* @param entityData The data of the entity
|
||||
* @param player Sends the entity to the player
|
||||
* @param delay Delays sending the entity to the player
|
||||
*/
|
||||
void sendEntityData(EntityData entityData, Player player, int delay);
|
||||
|
||||
/**
|
||||
* Cancels the entity scheduler
|
||||
*/
|
||||
void cancel();
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package re.imc.geysermodelengine.packet.entity;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.entity.EntityPositionData;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||
import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.*;
|
||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class PacketEntity {
|
||||
|
||||
private int id;
|
||||
private UUID uuid;
|
||||
private EntityType type;
|
||||
private Set<Player> viewers;
|
||||
private Location location;
|
||||
private float headYaw;
|
||||
private float headPitch;
|
||||
|
||||
private boolean removed = false;
|
||||
|
||||
public PacketEntity(EntityType type, Set<Player> viewers, Location location) {
|
||||
this.id = ThreadLocalRandom.current().nextInt(300000000, 400000000);
|
||||
this.uuid = UUID.randomUUID();
|
||||
this.type = type;
|
||||
this.viewers = viewers;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public @NotNull Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public boolean teleport(@NotNull Location location) {
|
||||
boolean sent = this.location.getWorld() != location.getWorld() || this.location.distanceSquared(location) > 0.000001 || this.location.getYaw() != location.getYaw() || this.location.getPitch() != location.getPitch();
|
||||
this.location = location.clone();
|
||||
|
||||
if (sent) sendLocationPacket(viewers);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
removed = true;
|
||||
sendEntityDestroyPacket(viewers);
|
||||
}
|
||||
|
||||
public boolean isDead() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return !removed;
|
||||
}
|
||||
|
||||
public void sendSpawnPacket(Collection<Player> players) {
|
||||
WrapperPlayServerSpawnEntity spawnEntity = new WrapperPlayServerSpawnEntity(id, uuid, type, SpigotConversionUtil.fromBukkitLocation(location), location.getYaw(), 0, null);
|
||||
players.forEach(player -> PacketEvents.getAPI().getPlayerManager().sendPacket(player, spawnEntity));
|
||||
}
|
||||
|
||||
public void sendLocationPacket(Collection<Player> players) {
|
||||
PacketWrapper<?> packet;
|
||||
EntityPositionData data = new EntityPositionData(SpigotConversionUtil.fromBukkitLocation(location).getPosition(), Vector3d.zero(), location.getYaw(), location.getPitch());
|
||||
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) {
|
||||
packet = new WrapperPlayServerEntityPositionSync(id, data, false);
|
||||
} else {
|
||||
packet = new WrapperPlayServerEntityTeleport(id, data, RelativeFlag.NONE,false);
|
||||
}
|
||||
|
||||
players.forEach(player -> PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet));
|
||||
}
|
||||
|
||||
public void sendHeadRotation(Collection<Player> players) {
|
||||
WrapperPlayServerEntityRotation packet = new WrapperPlayServerEntityRotation(id, headYaw, headPitch, false);
|
||||
players.forEach(player -> PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet));
|
||||
}
|
||||
|
||||
public void sendEntityDestroyPacket(Collection<Player> players) {
|
||||
WrapperPlayServerDestroyEntities packet = new WrapperPlayServerDestroyEntities(id);
|
||||
players.forEach(player -> PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet));
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package re.imc.geysermodelengine.runnables;
|
||||
|
||||
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.bone.type.Mount;
|
||||
import com.ticxo.modelengine.api.mount.controller.MountController;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BedrockMountControlRunnable implements Runnable {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
public BedrockMountControlRunnable(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (UUID playerUUID : plugin.getModelManager().getPlayerJoinedCache()) {
|
||||
Player player = Bukkit.getPlayer(playerUUID);
|
||||
|
||||
float pitch = player.getLocation().getPitch();
|
||||
Pair<ActiveModel, Mount> seat = plugin.getModelManager().getDriversCache().get(player.getUniqueId());
|
||||
if (seat == null) continue;
|
||||
|
||||
if (pitch < -30) {
|
||||
MountController controller = ModelEngineAPI.getMountPairManager().getController(player.getUniqueId());
|
||||
if (controller != null) {
|
||||
MountController.MountInput input = controller.getInput();
|
||||
if (input != null) {
|
||||
input.setJump(true);
|
||||
controller.setInput(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pitch > 80) {
|
||||
if (seat.getKey().getModeledEntity().getBase() instanceof BukkitEntity bukkitEntity) {
|
||||
if (bukkitEntity.getOriginal().isOnGround()) continue;
|
||||
}
|
||||
|
||||
MountController controller = ModelEngineAPI.getMountPairManager().getController(player.getUniqueId());
|
||||
if (controller != null) {
|
||||
MountController.MountInput input = controller.getInput();
|
||||
if (input != null) {
|
||||
input.setSneak(true);
|
||||
controller.setInput(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package re.imc.geysermodelengine.runnables;
|
||||
|
||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||
import re.imc.geysermodelengine.managers.model.entity.EntityData;
|
||||
import re.imc.geysermodelengine.managers.model.model.Model;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class UpdateTaskRunnable implements Runnable {
|
||||
|
||||
private final GeyserModelEngine plugin;
|
||||
|
||||
public UpdateTaskRunnable(GeyserModelEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ConcurrentHashMap<Integer, Map<Model, EntityData>> entitiesCache = plugin.getModelManager().getEntitiesCache();
|
||||
if (entitiesCache.isEmpty()) return;
|
||||
|
||||
try {
|
||||
for (Map<Model, EntityData> models : entitiesCache.values()) {
|
||||
models.values().forEach(entityData -> {
|
||||
if (entityData.getViewers().isEmpty()) return;
|
||||
plugin.getEntityTaskManager().getPropertyHandler().updateEntityProperties(entityData, entityData.getViewers(), false);
|
||||
});
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
throw new RuntimeException(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package re.imc.geysermodelengine.util;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
|
||||
public class BedrockUtils {
|
||||
|
||||
private static FloodgateApi FLOODGATE_API;
|
||||
|
||||
public static boolean isBedrockPlayer(Player player) {
|
||||
if (FLOODGATE_API != null) return FLOODGATE_API.isFloodgatePlayer(player.getUniqueId());
|
||||
return player.getClientBrandName().contains("Geyser");
|
||||
}
|
||||
|
||||
public static FloodgateApi getFloodgateApi() {
|
||||
return FLOODGATE_API;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package re.imc.geysermodelengine.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class BooleanPacker {
|
||||
|
||||
private static final int MAX_BOOLEANS = 24;
|
||||
|
||||
public static int booleansToInt(List<Boolean> booleans) {
|
||||
int result = 0;
|
||||
int i = 1;
|
||||
|
||||
for (boolean b : booleans) {
|
||||
if (b) {
|
||||
result += i;
|
||||
}
|
||||
i *= 2;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int mapBooleansToInt(Map<String, Boolean> booleanMap) {
|
||||
int result = 0;
|
||||
int i = 1;
|
||||
|
||||
List<String> keys = new ArrayList<>(booleanMap.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
for (String key : keys) {
|
||||
if (booleanMap.get(key)) {
|
||||
result += i;
|
||||
}
|
||||
i *= 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<Integer> booleansToInts(List<Boolean> booleans) {
|
||||
List<Integer> results = new ArrayList<>();
|
||||
int result = 0;
|
||||
int i = 1;
|
||||
int i1 = 1;
|
||||
|
||||
for (boolean b : booleans) {
|
||||
if (b) {
|
||||
result += i;
|
||||
}
|
||||
if (i1 % MAX_BOOLEANS == 0 || i1 == booleans.size()) {
|
||||
results.add(result);
|
||||
result = 0;
|
||||
i = 1;
|
||||
} else {
|
||||
i *= 2;
|
||||
}
|
||||
i1++;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public static List<Integer> mapBooleansToInts(Map<String, Boolean> booleanMap) {
|
||||
List<String> keys = new ArrayList<>(booleanMap.keySet());
|
||||
List<Boolean> booleans = new ArrayList<>();
|
||||
|
||||
Collections.sort(keys);
|
||||
|
||||
for (String key : keys) {
|
||||
booleans.add(booleanMap.get(key));
|
||||
}
|
||||
return booleansToInts(booleans);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package re.imc.geysermodelengine.util;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ColourUtils {
|
||||
|
||||
private final MiniMessage miniMessage = MiniMessage.miniMessage();
|
||||
|
||||
public @NotNull Component miniFormat(String message) {
|
||||
return miniMessage.deserialize(message).decoration(TextDecoration.ITALIC, false);
|
||||
}
|
||||
|
||||
public @NotNull Component miniFormat(String message, TagResolver tagResolver) {
|
||||
return miniMessage.deserialize(message, tagResolver).decoration(TextDecoration.ITALIC, false);
|
||||
}
|
||||
|
||||
public String stripColour(Component component) {
|
||||
return PlainTextComponentSerializer.plainText().serialize(component);
|
||||
}
|
||||
|
||||
public MiniMessage getMiniMessage() {
|
||||
return miniMessage;
|
||||
}
|
||||
}
|
||||
4
paper/src/main/resources/Lang/messages.yml
Normal file
4
paper/src/main/resources/Lang/messages.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
commands:
|
||||
reload:
|
||||
successfully-reloaded: "<#55FF55>GeyserModelEngine configuration reloaded!"
|
||||
13
paper/src/main/resources/config.yml
Normal file
13
paper/src/main/resources/config.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
metrics:
|
||||
bstats: true
|
||||
|
||||
models:
|
||||
namespace: "modelengine"
|
||||
data-send-delay: 5
|
||||
entity-view-distance: 50
|
||||
join-send-delay: 20
|
||||
entity-position-update-period: 35
|
||||
thread-pool-size: 4
|
||||
|
||||
options:
|
||||
debug: false
|
||||
24
paper/src/main/resources/paper-plugin.yml
Normal file
24
paper/src/main/resources/paper-plugin.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
main: re.imc.geysermodelengine.GeyserModelEngine
|
||||
name: GeyserModelEngine
|
||||
version: '1.0.0'
|
||||
api-version: '1.21'
|
||||
|
||||
authors:
|
||||
- zimzaza4
|
||||
- willem.dev
|
||||
- xSquishyLiam
|
||||
|
||||
load: STARTUP
|
||||
|
||||
dependencies:
|
||||
server:
|
||||
GeyserUtils:
|
||||
required: true
|
||||
packetevents:
|
||||
required: true
|
||||
floodgate:
|
||||
required: false
|
||||
ModelEngine:
|
||||
required: false
|
||||
BetterModel:
|
||||
required: false
|
||||
Reference in New Issue
Block a user