SteamWar/FightSystem
Archiviert
13
1
Dieses Repository wurde am 2024-08-05 archiviert. Du kannst Dateien ansehen und es klonen, aber nicht pushen oder Issues/Pull-Requests öffnen.
FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/REntity.java
Lixfel 46325c0049
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Fix entity animation
Signed-off-by: Lixfel <agga-games@gmx.de>
2022-04-01 15:56:12 +02:00

349 Zeilen
16 KiB
Java

/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.record;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import com.mojang.authlib.GameProfile;
import de.steamwar.core.Core;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.listener.FightScoreboard;
import de.steamwar.fightsystem.utils.*;
import de.steamwar.sql.SteamwarUser;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scoreboard.NameTagVisibility;
import org.bukkit.scoreboard.Team;
import java.util.*;
import java.util.logging.Level;
public class REntity {
private static final Map<Integer, REntity> entities = new HashMap<>();
public static REntity getEntity(int internalId){
return entities.get(internalId);
}
private static Object entityStatusWatcher;
private static Object sneakingDataWatcher;
private static Object bowDrawnWatcher;
public static void initWatchers() {
// not during <clinit> to prevent cyclic class init.
entityStatusWatcher = BountifulWrapper.impl.getDataWatcherObject(0, Byte.class);
sneakingDataWatcher = BountifulWrapper.impl.getDataWatcherObject(Core.getVersion() > 12 ? 6 : 0, BlockIdWrapper.impl.getPose(true).getClass());
bowDrawnWatcher = BountifulWrapper.impl.getDataWatcherObject(Core.getVersion() > 12 ? 7 : 6, Byte.class);
}
public static void tickFire() {
entities.forEach((integer, entity) -> {
if(entity.fireTick > 0) {
entity.fireTick--;
if(entity.fireTick == 0) {
ProtocolAPI.broadcastPacket(entity.getDataWatcherPacket(entityStatusWatcher, (byte)0));
}
}
});
}
public static void playerJoins(Player player) {
for(REntity entity : entities.values()){
if(entity.entityType == EntityType.PLAYER){
TinyProtocol.instance.sendPacket(player, entity.getPlayerInfoPacket());
TinyProtocol.instance.sendPacket(player, entity.getNamedSpawnPacket());
for (Map.Entry<String, ItemStack> entry : entity.itemSlots.entrySet()) {
TinyProtocol.instance.sendPacket(player, entity.getEquipmentPacket(entry.getKey(), entry.getValue()));
}
}else{
TinyProtocol.instance.sendPacket(player, entity.getSpawnEntityPacket());
}
TinyProtocol.instance.sendPacket(player, entity.getTeleportPacket());
TinyProtocol.instance.sendPacket(player, entity.getHeadRotationPacket());
if(entity.fireTick != 0) {
TinyProtocol.instance.sendPacket(player, entity.getDataWatcherPacket(entityStatusWatcher, (byte) 1));
}
if(entity.sneaks) {
TinyProtocol.instance.sendPacket(player, entity.getDataWatcherPacket(sneakingDataWatcher, BlockIdWrapper.impl.getPose(true)));
}
}
}
public static void dieAll(){
entities.forEach((id, entity) -> entity.broadcastDeath());
entities.clear();
}
private static final String SCOREBOARD_TEAMNAME = "Replay";
private static final Team team;
static {
if(FightScoreboard.getBukkit().getTeam(SCOREBOARD_TEAMNAME) == null)
team = FightScoreboard.getBukkit().registerNewTeam(SCOREBOARD_TEAMNAME);
else
team = FightScoreboard.getBukkit().getTeam(SCOREBOARD_TEAMNAME);
team.setNameTagVisibility(NameTagVisibility.NEVER);
}
private static int entityCount = Integer.MAX_VALUE;
private static final Random random = new Random();
private final int internalId;
private final int entityId;
private final UUID uuid;
private final EntityType entityType;
private final String name;
private final Map<String, ItemStack> itemSlots = new HashMap<>();
private double locX;
private double locY;
private double locZ;
private byte yaw;
private byte pitch;
private byte headYaw;
private int fireTick;
private boolean sneaks;
private boolean playerSpawned = false;
public REntity(int internalId, int userId){
this.internalId = internalId;
this.entityType = EntityType.PLAYER;
this.entityId = entityCount--;
SteamwarUser user;
try {
user = SteamwarUser.get(userId);
} catch (SecurityException e) {
FightSystem.getPlugin().getLogger().log(Level.SEVERE, "Could not load user " + userId);
throw e;
}
this.uuid = user.getUUID();
this.name = user.getUserName();
entities.put(internalId, this);
ProtocolAPI.broadcastPacket(getPlayerInfoPacket());
team.addEntry(name);
}
public REntity(int internalId, EntityType entityType){
this.internalId = internalId;
this.entityType = entityType;
this.entityId = entityCount--;
this.name = null;
this.uuid = new UUID(random.nextLong() & -61441L | 16384L, random.nextLong() & 4611686018427387903L | -9223372036854775808L);
entities.put(internalId, this);
ProtocolAPI.broadcastPacket(getSpawnEntityPacket());
}
public void move(double locX, double locY, double locZ, float pitch, float yaw, byte headYaw){
this.locX = locX;
this.locY = locY;
this.locZ = locZ;
if(entityType == EntityType.PLAYER && !playerSpawned) {
ProtocolAPI.broadcastPacket(getNamedSpawnPacket());
playerSpawned = true;
}
this.yaw = (byte)((int)(yaw * 256.0F / 360.0F));
this.pitch = (byte)((int)(pitch * 256.0F / 360.0F));
this.headYaw = headYaw;
ProtocolAPI.broadcastPacket(getTeleportPacket());
ProtocolAPI.broadcastPacket(getHeadRotationPacket());
}
private static final Class<?> animationPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutAnimation");
private static final Reflection.FieldAccessor<Integer> animationEntity = Reflection.getField(animationPacket, int.class, Core.getVersion() > 15 ? 6 : 0);
private static final Reflection.FieldAccessor<Integer> animationAnimation = Reflection.getField(animationPacket, int.class, Core.getVersion() > 15 ? 7 : 1);
public void animation(byte animation) {
Object packet = Reflection.newInstance(animationPacket);
animationEntity.set(packet, entityId);
animationAnimation.set(packet, (int) animation);
ProtocolAPI.broadcastPacket(packet);
}
private static final Class<?> velocityPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityVelocity");
private static final Reflection.FieldAccessor<Integer> velocityEntity = Reflection.getField(velocityPacket, int.class, 0);
private static final Reflection.FieldAccessor<Integer> velocityX = Reflection.getField(velocityPacket, int.class, 1);
private static final Reflection.FieldAccessor<Integer> velocityY = Reflection.getField(velocityPacket, int.class, 2);
private static final Reflection.FieldAccessor<Integer> velocityZ = Reflection.getField(velocityPacket, int.class, 3);
public void setVelocity(double dX, double dY, double dZ) {
Object packet = Reflection.newInstance(velocityPacket);
velocityEntity.set(packet, entityId);
velocityX.set(packet, calcVelocity(dX));
velocityY.set(packet, calcVelocity(dY));
velocityZ.set(packet, calcVelocity(dZ));
ProtocolAPI.broadcastPacket(packet);
}
private static final Class<?> statusPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityStatus");
private static final Reflection.FieldAccessor<Integer> statusEntity = Reflection.getField(statusPacket, int.class, 0);
private static final Reflection.FieldAccessor<Byte> statusStatus = Reflection.getField(statusPacket, byte.class, 0);
public void damage() {
Object packet = Reflection.newInstance(statusPacket);
statusEntity.set(packet, entityId);
statusStatus.set(packet, (byte) 2);
ProtocolAPI.broadcastPacket(packet);
}
public void sneak(boolean sneaking) {
sneaks = sneaking;
ProtocolAPI.broadcastPacket(getDataWatcherPacket(sneakingDataWatcher, BlockIdWrapper.impl.getPose(sneaking)));
}
public void setOnFire(boolean perma) {
if(!perma) {
fireTick = 21;
} else {
fireTick = -1;
}
ProtocolAPI.broadcastPacket(getDataWatcherPacket(entityStatusWatcher, (byte) 1));
}
public void setBowDrawn(boolean drawn, boolean offHand) {
if(Core.getVersion() > 8){
ProtocolAPI.broadcastPacket(getDataWatcherPacket(bowDrawnWatcher, (byte) ((drawn ? 1 : 0) + (offHand ? 2 : 0))));
}else{
ProtocolAPI.broadcastPacket(getDataWatcherPacket(entityStatusWatcher, (byte)0x10));
}
}
public void setItem(String item, boolean enchanted, String slot) {
ItemStack stack = new ItemStack(Material.valueOf(item.replace("minecraft:", "").toUpperCase()), 1);
if(enchanted)
stack.addUnsafeEnchantment(Enchantment.DURABILITY, 1);
itemSlots.put(slot, stack);
ProtocolAPI.broadcastPacket(getEquipmentPacket(slot, stack));
}
public void die(){
broadcastDeath();
entities.remove(internalId);
}
private static final Class<?> destroyPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityDestroy");
private static final Reflection.FieldAccessor<?> destroyEntities;
static {
if(Core.getVersion() > 15)
destroyEntities = Reflection.getField(destroyPacket, IntList.class, 0);
else
destroyEntities = Reflection.getField(destroyPacket, int[].class, 0);
}
private void broadcastDeath(){
if(entityType == EntityType.PLAYER){
ProtocolAPI.broadcastPacket(Fight.playerInfoPacket(Fight.removePlayer, new GameProfile(uuid, name), Fight.creative));
team.removeEntry(name);
}
Object packet = Reflection.newInstance(destroyPacket);
destroyEntities.set(packet, Core.getVersion() > 15 ? new IntArrayList(new int[]{entityId}) : new int[]{entityId});
ProtocolAPI.broadcastPacket(packet);
}
private int calcVelocity(double value) {
return (int)(Math.max(-3.9, Math.min(value, 3.9)) * 8000);
}
private static final Class<?> metadataPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityMetadata");
private static final Reflection.FieldAccessor<Integer> metadataEntity = Reflection.getField(metadataPacket, int.class, 0);
private static final Reflection.FieldAccessor<List> metadataMetadata = Reflection.getField(metadataPacket, List.class, 0);
private Object getDataWatcherPacket(Object dataWatcherObject, Object value) {
Object packet = Reflection.newInstance(metadataPacket);
metadataEntity.set(packet, entityId);
metadataMetadata.set(packet, Collections.singletonList(BountifulWrapper.impl.getDataWatcherItem(dataWatcherObject, value)));
return packet;
}
public static final Class<?> teleportPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityTeleport");
private static final Reflection.FieldAccessor<Integer> teleportEntity = Reflection.getField(teleportPacket, int.class, 0);
private static final Reflection.FieldAccessor<Byte> teleportYaw = Reflection.getField(teleportPacket, byte.class, 0);
private static final Reflection.FieldAccessor<Byte> teleportPitch = Reflection.getField(teleportPacket, byte.class, 1);
private Object getTeleportPacket(){
Object packet = Reflection.newInstance(teleportPacket);
teleportEntity.set(packet, entityId);
BountifulWrapper.impl.setTeleportPacketPosition(packet, locX, locY, locZ);
teleportYaw.set(packet, yaw);
teleportPitch.set(packet, pitch);
return packet;
}
private static final Class<?> headRotationPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityHeadRotation");
private static final Reflection.FieldAccessor<Integer> headRotationEntity = Reflection.getField(headRotationPacket, int.class, 0);
private static final Reflection.FieldAccessor<Byte> headRotationYaw = Reflection.getField(headRotationPacket, byte.class, 0);
private Object getHeadRotationPacket(){
Object packet = Reflection.newInstance(headRotationPacket);
headRotationEntity.set(packet, entityId);
headRotationYaw.set(packet, headYaw);
return packet;
}
public static final Class<?> spawnPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutSpawnEntity");
private static final Reflection.FieldAccessor<Integer> spawnEntity = Reflection.getField(spawnPacket, int.class, 0);
private Object getSpawnEntityPacket(){
Object packet = Reflection.newInstance(spawnPacket);
spawnEntity.set(packet, entityId);
BountifulWrapper.impl.setSpawnPacketUUID(packet, uuid);
ProtocolWrapper.impl.setSpawnPacketType(packet, entityType);
return packet;
}
public static final Class<?> equipmentPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityEquipment");
private static final Reflection.FieldAccessor<Integer> equipmentEntity = Reflection.getField(equipmentPacket, int.class, 0);
public static final Class<?> itemStack = Reflection.getClass("{nms.world.item}.ItemStack");
private static final Class<?> craftItemStack = Reflection.getClass("{obc}.inventory.CraftItemStack");
private static final Reflection.MethodInvoker asNMSCopy = Reflection.getTypedMethod(REntity.craftItemStack, "asNMSCopy", REntity.itemStack, ItemStack.class);
private Object getEquipmentPacket(String slot, ItemStack stack){
Object packet = Reflection.newInstance(equipmentPacket);
equipmentEntity.set(packet, entityId);
ProtocolWrapper.impl.setEquipmentPacketStack(packet, slot, asNMSCopy.invoke(null, stack));
return packet;
}
private Object getPlayerInfoPacket(){
return Fight.playerInfoPacket(Fight.addPlayer, new GameProfile(uuid, name), Fight.creative);
}
public static final Class<?> namedSpawnPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutNamedEntitySpawn");
private static final Reflection.FieldAccessor<Integer> namedSpawnEntity = Reflection.getField(namedSpawnPacket, int.class, 0);
private static final Reflection.FieldAccessor<UUID> namedSpawnUUID = Reflection.getField(namedSpawnPacket, UUID.class, 0);
private Object getNamedSpawnPacket(){
Object packet = Reflection.newInstance(namedSpawnPacket);
namedSpawnEntity.set(packet, entityId);
namedSpawnUUID.set(packet, uuid);
BountifulWrapper.impl.setNamedSpawnPosition(packet, locX, locY, locZ);
FlatteningWrapper.impl.setNamedSpawnPacketDataWatcher(packet);
return packet;
}
}