mirror of
https://github.com/GeyserExtensionists/GeyserModelEngine.git
synced 2025-12-19 15:09:18 +00:00
ahhh reuse boolean anim property
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package re.imc.geysermodelengine.listener;
|
package re.imc.geysermodelengine.listener;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||||
import com.comphenix.protocol.wrappers.Pair;
|
import com.comphenix.protocol.wrappers.Pair;
|
||||||
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
||||||
import com.ticxo.modelengine.api.ModelEngineAPI;
|
import com.ticxo.modelengine.api.ModelEngineAPI;
|
||||||
@@ -10,6 +11,7 @@ import com.ticxo.modelengine.api.model.ModeledEntity;
|
|||||||
import com.ticxo.modelengine.api.model.render.ModelRenderer;
|
import com.ticxo.modelengine.api.model.render.ModelRenderer;
|
||||||
import me.zimzaza4.geyserutils.spigot.api.EntityUtils;
|
import me.zimzaza4.geyserutils.spigot.api.EntityUtils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
@@ -21,6 +23,7 @@ import org.bukkit.event.entity.*;
|
|||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
import org.bukkit.event.world.EntitiesLoadEvent;
|
import org.bukkit.event.world.EntitiesLoadEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.metadata.FixedMetadataValue;
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||||
|
|||||||
@@ -8,15 +8,12 @@ import com.ticxo.modelengine.api.model.bone.ModelBone;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import me.zimzaza4.geyserutils.common.animation.Animation;
|
import me.zimzaza4.geyserutils.common.animation.Animation;
|
||||||
import me.zimzaza4.geyserutils.spigot.GeyserUtils;
|
|
||||||
import me.zimzaza4.geyserutils.spigot.api.EntityUtils;
|
import me.zimzaza4.geyserutils.spigot.api.EntityUtils;
|
||||||
import me.zimzaza4.geyserutils.spigot.api.PlayerUtils;
|
import me.zimzaza4.geyserutils.spigot.api.PlayerUtils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||||
import re.imc.geysermodelengine.packet.entity.PacketEntity;
|
import re.imc.geysermodelengine.packet.entity.PacketEntity;
|
||||||
@@ -24,7 +21,6 @@ import re.imc.geysermodelengine.packet.entity.PacketEntity;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import static re.imc.geysermodelengine.model.ModelEntity.ENTITIES;
|
import static re.imc.geysermodelengine.model.ModelEntity.ENTITIES;
|
||||||
import static re.imc.geysermodelengine.model.ModelEntity.MODEL_ENTITIES;
|
import static re.imc.geysermodelengine.model.ModelEntity.MODEL_ENTITIES;
|
||||||
@@ -33,7 +29,8 @@ import static re.imc.geysermodelengine.model.ModelEntity.MODEL_ENTITIES;
|
|||||||
@Setter
|
@Setter
|
||||||
public class EntityTask {
|
public class EntityTask {
|
||||||
|
|
||||||
private static final String ANIMATION_PROPERTY = "modelengine:anim";
|
private static final String STOP_ANIMATION_PROPERTY = "anim_stop";
|
||||||
|
private static final Map<String, Boolean> ALL_PROPERTIES = Map.of("modelengine:anim_walk", false, "modelengine:anim_idle", false, "modelengine:anim_stop", false);
|
||||||
ModelEntity model;
|
ModelEntity model;
|
||||||
|
|
||||||
int tick = 0;
|
int tick = 0;
|
||||||
@@ -51,8 +48,8 @@ public class EntityTask {
|
|||||||
|
|
||||||
|
|
||||||
String lastAnimation = "";
|
String lastAnimation = "";
|
||||||
int currentAnimProperty = 1;
|
Map<String, Boolean> lastAnimPropertySet = new HashMap<>();
|
||||||
int lastAnimProperty = -1;
|
|
||||||
|
|
||||||
boolean looping = true;
|
boolean looping = true;
|
||||||
|
|
||||||
@@ -149,17 +146,14 @@ public class EntityTask {
|
|||||||
} else if (base.isJumping() && hasAnimation("jump")) {
|
} else if (base.isJumping() && hasAnimation("jump")) {
|
||||||
playAnimation("jump", 30);
|
playAnimation("jump", 30);
|
||||||
} else if (base.isWalking() && hasAnimation("walk")) {
|
} else if (base.isWalking() && hasAnimation("walk")) {
|
||||||
setAnimationProperty(3);
|
playAnimation("walk", 20);
|
||||||
// playAnimation("walk", 20);
|
|
||||||
} else if (hasAnimation("idle")) {
|
} else if (hasAnimation("idle")) {
|
||||||
// playAnimation("idle", 0);
|
playAnimation("idle", 0);
|
||||||
setAnimationProperty(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animationCooldown.get() > 0) {
|
if (animationCooldown.get() > 0) {
|
||||||
animationCooldown.decrementAndGet();
|
animationCooldown.decrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Player> player = viewers.stream().findAny();
|
Optional<Player> player = viewers.stream().findAny();
|
||||||
if (player.isEmpty()) return;
|
if (player.isEmpty()) return;
|
||||||
|
|
||||||
@@ -168,6 +162,7 @@ public class EntityTask {
|
|||||||
// do not actually use this, atleast bundle these up ;(
|
// do not actually use this, atleast bundle these up ;(
|
||||||
sendScale(player.get(), true);
|
sendScale(player.get(), true);
|
||||||
sendColor(player.get(), true);
|
sendColor(player.get(), true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendSpawnPacket(Player onlinePlayer) {
|
private void sendSpawnPacket(Player onlinePlayer) {
|
||||||
@@ -223,10 +218,26 @@ public class EntityTask {
|
|||||||
|
|
||||||
lastColor = color;
|
lastColor = color;
|
||||||
}
|
}
|
||||||
|
public void setAnimationProperty(String currentAnimProperty) {
|
||||||
|
|
||||||
public void setAnimationProperty(int currentAnimProperty) {
|
Map<String, Boolean> updates = new HashMap<>(ALL_PROPERTIES);
|
||||||
this.lastAnimProperty = currentAnimProperty;
|
|
||||||
this.currentAnimProperty = currentAnimProperty;
|
Optional<Player> player = model.getViewers().stream().findAny();
|
||||||
|
if (player.isEmpty()) return;
|
||||||
|
|
||||||
|
if (animationCooldown.get() == 0) {
|
||||||
|
updates.put("modelengine:" + currentAnimProperty, true);
|
||||||
|
} else {
|
||||||
|
updates.put("modelengine:" + STOP_ANIMATION_PROPERTY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updates.equals(lastAnimPropertySet)) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
lastAnimPropertySet.clear();
|
||||||
|
lastAnimPropertySet.putAll(updates);
|
||||||
|
}
|
||||||
|
EntityUtils.sendBoolProperties(player.get(), model.getEntity().getEntityId(), updates);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateEntityProperties(Player player, boolean ignore) {
|
public void updateEntityProperties(Player player, boolean ignore) {
|
||||||
@@ -252,20 +263,24 @@ public class EntityTask {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
int animationUpdate = -1;
|
/*
|
||||||
|
if (!lastAnimProperty.equals(currentAnimProperty)) {
|
||||||
|
|
||||||
if (ignore || !(lastAnimProperty == currentAnimProperty)) {
|
player.sendMessage("CHANGED");
|
||||||
if (animationCooldown.get() == 0) {
|
if (animationCooldown.get() == 0) {
|
||||||
animationUpdate = currentAnimProperty;
|
player.sendMessage(lastAnimProperty + " -> " + currentAnimProperty);
|
||||||
|
|
||||||
|
updates.put("modelengine:" + lastAnimProperty, false);
|
||||||
|
updates.put("modelengine:" + currentAnimProperty, true);
|
||||||
} else {
|
} else {
|
||||||
animationUpdate = 0;
|
updates.put("modelengine:" + lastAnimProperty, false);
|
||||||
|
updates.put("modelengine:" + STOP_ANIMATION_PROPERTY, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (animationUpdate != -1) {
|
|
||||||
EntityUtils.sendIntProperty(player, entity, ANIMATION_PROPERTY, animationUpdate);
|
|
||||||
}
|
|
||||||
if (updates.isEmpty()) return;
|
if (updates.isEmpty()) return;
|
||||||
|
player.sendMessage("SEND: " + updates);
|
||||||
|
|
||||||
|
*/
|
||||||
EntityUtils.sendBoolProperties(player, entity, updates);
|
EntityUtils.sendBoolProperties(player, entity, updates);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,6 +326,14 @@ public class EntityTask {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (animationProperty.getName().equalsIgnoreCase("walk")) {
|
||||||
|
setAnimationProperty("anim_walk");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (animationProperty.getName().equalsIgnoreCase("idle")) {
|
||||||
|
setAnimationProperty("anim_idle");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
boolean play = false;
|
boolean play = false;
|
||||||
if (currentAnimationPriority.get() < p) {
|
if (currentAnimationPriority.get() < p) {
|
||||||
@@ -327,17 +350,17 @@ public class EntityTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (play) {
|
if (play) {
|
||||||
setAnimationProperty(0);
|
// setAnimationProperty(0);
|
||||||
|
|
||||||
currentAnimationPriority.set(p);
|
currentAnimationPriority.set(p);
|
||||||
|
|
||||||
String id = "animation." + activeModel.getBlueprint().getName().toLowerCase() + "." + animationProperty.getName().toLowerCase();
|
String id = "animation." + activeModel.getBlueprint().getName().toLowerCase() + "." + animationProperty.getName().toLowerCase();
|
||||||
lastAnimation = id;
|
lastAnimation = id;
|
||||||
animationCooldown.set((int) (animationProperty.getLength() * 20));
|
animationCooldown.set((int) Math.min(Math.floor(animationProperty.getLength() * 20) - 3, 1));
|
||||||
|
|
||||||
playBedrockAnimation(id, model.getViewers(), looping, blendTime);
|
playBedrockAnimation(id, model.getViewers(), looping, blendTime);
|
||||||
|
setAnimationProperty("stop");
|
||||||
}
|
}
|
||||||
return animationCooldown.get();
|
return animationCooldown.get();
|
||||||
}
|
}
|
||||||
@@ -365,9 +388,6 @@ public class EntityTask {
|
|||||||
|
|
||||||
|
|
||||||
public void playBedrockAnimation(String animationId, Set<Player> viewers, boolean loop, float blendTime) {
|
public void playBedrockAnimation(String animationId, Set<Player> viewers, boolean loop, float blendTime) {
|
||||||
|
|
||||||
// model.getViewers().forEach(viewer -> viewer.sendActionBar("CURRENT AN:" + animationId));
|
|
||||||
|
|
||||||
int entity = model.getEntity().getEntityId();
|
int entity = model.getEntity().getEntityId();
|
||||||
|
|
||||||
Animation.AnimationBuilder animation = Animation.builder()
|
Animation.AnimationBuilder animation = Animation.builder()
|
||||||
@@ -416,12 +436,7 @@ public class EntityTask {
|
|||||||
public void run(GeyserModelEngine instance, int i) {
|
public void run(GeyserModelEngine instance, int i) {
|
||||||
|
|
||||||
String id = "";
|
String id = "";
|
||||||
ActiveModel activeModel = model.getActiveModel();
|
playAnimation("spawn", 30);
|
||||||
if (hasAnimation("spawn")) {
|
|
||||||
id = "animation." + activeModel.getBlueprint().getName().toLowerCase() + ".spawn";
|
|
||||||
} else {
|
|
||||||
id = "animation." + activeModel.getBlueprint().getName().toLowerCase() + ".idle";
|
|
||||||
}
|
|
||||||
|
|
||||||
lastAnimation = id;
|
lastAnimation = id;
|
||||||
sendHitBoxToAll();
|
sendHitBoxToAll();
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package re.imc.geysermodelengine.model;
|
package re.imc.geysermodelengine.model;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.ticxo.modelengine.api.model.ActiveModel;
|
import com.ticxo.modelengine.api.model.ActiveModel;
|
||||||
import com.ticxo.modelengine.api.model.ModeledEntity;
|
import com.ticxo.modelengine.api.model.ModeledEntity;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.metadata.FixedMetadataValue;
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
import re.imc.geysermodelengine.GeyserModelEngine;
|
import re.imc.geysermodelengine.GeyserModelEngine;
|
||||||
import re.imc.geysermodelengine.packet.entity.PacketEntity;
|
import re.imc.geysermodelengine.packet.entity.PacketEntity;
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package re.imc.geysermodelengine.packet;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.PacketType;
|
||||||
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
|
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class EntityEquipmentPacket implements WrapperPacket {
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
private final EnumWrappers.ItemSlot slot;
|
||||||
|
private final ItemStack itemStack;
|
||||||
|
public EntityEquipmentPacket(int id, EnumWrappers.ItemSlot slot, ItemStack itemStack) {
|
||||||
|
this.id = id;
|
||||||
|
this.slot = slot;
|
||||||
|
this.itemStack = itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PacketContainer encode() {
|
||||||
|
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
|
||||||
|
packet.getIntegers().writeSafely(0, id);
|
||||||
|
packet.getItemSlots().writeSafely(0, slot);
|
||||||
|
packet.getItemModifier().writeSafely(0, itemStack);
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,11 +14,11 @@ public class EntityHurtPacket implements WrapperPacket {
|
|||||||
@Override
|
@Override
|
||||||
public PacketContainer encode() {
|
public PacketContainer encode() {
|
||||||
PacketContainer packet = new PacketContainer(PacketType.Play.Server.DAMAGE_EVENT);
|
PacketContainer packet = new PacketContainer(PacketType.Play.Server.DAMAGE_EVENT);
|
||||||
packet.getIntegers().write(0, id);
|
packet.getIntegers().writeSafely(0, id);
|
||||||
packet.getIntegers().write(1,0);
|
packet.getIntegers().writeSafely(1,0);
|
||||||
packet.getIntegers().write(2, 0);
|
packet.getIntegers().writeSafely(2, 0);
|
||||||
packet.getIntegers().write(3, 0);
|
packet.getIntegers().writeSafely(3, 0);
|
||||||
packet.getBooleans().write(0, false);
|
packet.getBooleans().writeSafely(0, false);
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,24 @@
|
|||||||
package re.imc.geysermodelengine.packet.entity;
|
package re.imc.geysermodelengine.packet.entity;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
|
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||||
|
import lombok.Getter;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import re.imc.geysermodelengine.packet.*;
|
import re.imc.geysermodelengine.packet.*;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
@Getter
|
||||||
public class PacketEntity {
|
public class PacketEntity {
|
||||||
public PacketEntity(EntityType type, Set<Player> viewers, Location location) {
|
public PacketEntity(EntityType type, Set<Player> viewers, Location location) {
|
||||||
this.id = ThreadLocalRandom.current().nextInt(300000000, 400000000);
|
this.id = ThreadLocalRandom.current().nextInt(300000000, 400000000);
|
||||||
@@ -28,6 +35,8 @@ public class PacketEntity {
|
|||||||
private Location location;
|
private Location location;
|
||||||
private boolean removed = false;
|
private boolean removed = false;
|
||||||
|
|
||||||
|
private Map<EnumWrappers.ItemSlot, ItemStack> equipment = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public @NotNull Location getLocation() {
|
public @NotNull Location getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
@@ -59,9 +68,20 @@ public class PacketEntity {
|
|||||||
players.forEach(player -> {
|
players.forEach(player -> {
|
||||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode());
|
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode());
|
||||||
});
|
});
|
||||||
|
sendAllEquipmentPacket(players);
|
||||||
// players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, metadataPacket.encode()));
|
// players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, metadataPacket.encode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendAllEquipmentPacket(Collection<Player> players) {
|
||||||
|
for (Map.Entry<EnumWrappers.ItemSlot, ItemStack> e : equipment.entrySet()) {
|
||||||
|
EntityEquipmentPacket packet = new EntityEquipmentPacket(id, e.getKey(), e.getValue());
|
||||||
|
|
||||||
|
players.forEach(player -> {
|
||||||
|
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void sendLocationPacket(Collection<Player> players) {
|
public void sendLocationPacket(Collection<Player> players) {
|
||||||
EntityTeleportPacket packet = new EntityTeleportPacket(id, location);
|
EntityTeleportPacket packet = new EntityTeleportPacket(id, location);
|
||||||
players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode()));
|
players.forEach(player -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode()));
|
||||||
@@ -82,5 +102,16 @@ public class PacketEntity {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSlot(EnumWrappers.ItemSlot slot, ItemStack itemStack) {
|
||||||
|
if (itemStack == null) {
|
||||||
|
itemStack = new ItemStack(Material.AIR);
|
||||||
|
}
|
||||||
|
equipment.put(slot, itemStack);
|
||||||
|
EntityEquipmentPacket packet = new EntityEquipmentPacket(id, slot, itemStack);
|
||||||
|
viewers.forEach(player -> {
|
||||||
|
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet.encode());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user