diff --git a/src/de/steamwar/lobby/LobbySystem.java b/src/de/steamwar/lobby/LobbySystem.java index 977188a..0655238 100644 --- a/src/de/steamwar/lobby/LobbySystem.java +++ b/src/de/steamwar/lobby/LobbySystem.java @@ -24,6 +24,7 @@ import de.steamwar.lobby.command.FlyCommand; import de.steamwar.lobby.command.HologramCommand; import de.steamwar.lobby.command.PortalCommand; import de.steamwar.lobby.listener.*; +import de.steamwar.lobby.team.TeamPlayer; import de.steamwar.message.Message; import org.bukkit.plugin.java.JavaPlugin; @@ -56,6 +57,7 @@ public class LobbySystem extends JavaPlugin { new ParticleListener(); new InventoryInteraction(); new WorldInteraction(); + new TeamPlayer(); new AlphaWall(l -> l.getX() > 1199, AlphaWall.REFLECT_X); new AlphaWall(l -> l.getX() < 2977, AlphaWall.REFLECT_X); @@ -64,6 +66,10 @@ public class LobbySystem extends JavaPlugin { } + @Override + public void onDisable() { + TeamPlayer.cleanup(); + } public static LobbySystem getPlugin() { return plugin; diff --git a/src/de/steamwar/lobby/display/Displayable.java b/src/de/steamwar/lobby/display/Displayable.java index 0d7b272..327b83d 100644 --- a/src/de/steamwar/lobby/display/Displayable.java +++ b/src/de/steamwar/lobby/display/Displayable.java @@ -38,24 +38,34 @@ public class Displayable extends BasicListener { private final Set visible = new HashSet<>(); - private final int chunkX; - private final int chunkZ; + private int chunkX; + private int chunkZ; private final Consumer show; private final Consumer hide; + private final Consumer move; private final Function playerFilter; - public Displayable(Location location, Consumer show, Consumer hide) { - this(location, show, hide, player -> true); + public Displayable(Location location, Consumer show, Consumer hide, Consumer move) { + this(location, show, hide, move, player -> true); } public Displayable(Location location, Consumer show, Consumer hide, Function playerFilter) { - this.chunkX = posToChunk(location.getX()); - this.chunkZ = posToChunk(location.getZ()); + this(location, show, hide, player -> {}, playerFilter); + } + + public Displayable(Location location, Consumer show, Consumer hide, Consumer move, Function playerFilter) { this.show = show; this.hide = hide; + this.move = move; this.playerFilter = playerFilter; + setLocation(location); + } + public void setLocation(Location location) { + chunkX = posToChunk(location.getX()); + chunkZ = posToChunk(location.getZ()); Bukkit.getOnlinePlayers().forEach(this::checkLocation); + visible.forEach(move); } public Set getVisitors() { diff --git a/src/de/steamwar/lobby/display/NPC.java b/src/de/steamwar/lobby/display/NPC.java index 4a56d02..e24c3f2 100644 --- a/src/de/steamwar/lobby/display/NPC.java +++ b/src/de/steamwar/lobby/display/NPC.java @@ -62,6 +62,15 @@ public class NPC { private static final Reflection.ConstructorInvoker headRotationConstructor = Reflection.getConstructor(headRotationPacket); private static final Reflection.FieldAccessor headRotationEntity = Reflection.getField(headRotationPacket, int.class, 0); private static final Reflection.FieldAccessor headRotationYaw = Reflection.getField(headRotationPacket, byte.class, 0); + private static final Class movePacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityTeleport"); + private static final Reflection.ConstructorInvoker movePacketConstructor = Reflection.getConstructor(movePacket); + private static final Reflection.FieldAccessor movePacketEntity = Reflection.getField(movePacket, int.class, 0); + private static final Reflection.FieldAccessor movePacketX = Reflection.getField(movePacket, double.class, 0); + private static final Reflection.FieldAccessor movePacketY = Reflection.getField(movePacket, double.class, 1); + private static final Reflection.FieldAccessor movePacketZ = Reflection.getField(movePacket, double.class, 2); + private static final Reflection.FieldAccessor movePacketYaw = Reflection.getField(movePacket, byte.class, 0); + private static final Reflection.FieldAccessor movePacketPitch = Reflection.getField(movePacket, byte.class, 1); + private static final Reflection.FieldAccessor movePacketOnGround = Reflection.getField(movePacket, boolean.class, 0); private final Displayable display; @@ -75,6 +84,7 @@ public class NPC { private final Object headRotation; private final Object removePlayerInfo; private final Object destroy; + private Object move; public NPC(Location location, UUID uuid, String name) { this.entityId = Hologram.createEntityId(); @@ -101,7 +111,21 @@ public class NPC { headRotationEntity.set(headRotation, entityId); headRotationYaw.set(headRotation, yaw); - display = new Displayable(location, this::show, this::hide); + display = new Displayable(location, this::show, this::hide, this::move); + } + + public void setLocation(Location location) { + byte yaw = (byte)(int)(location.getYaw() * 256.0 / 360.0); + headRotationYaw.set(headRotation, yaw); + move = movePacketConstructor.invoke(); + movePacketEntity.set(move, entityId); + movePacketX.set(move, location.getX()); + movePacketY.set(move, location.getY()); + movePacketZ.set(move, location.getZ()); + movePacketYaw.set(move, yaw); + movePacketPitch.set(move, (byte)(int)(location.getPitch() * 256.0 / 360.0)); + movePacketOnGround.set(move, true); + display.setLocation(location); } public Location getLocation() { @@ -123,6 +147,11 @@ public class NPC { TinyProtocol.instance.sendPacket(player, destroy); } + private void move(Player player) { + TinyProtocol.instance.sendPacket(player, headRotation); + TinyProtocol.instance.sendPacket(player, move); + } + public void delete() { display.delete(); } diff --git a/src/de/steamwar/lobby/team/TeamPlayer.java b/src/de/steamwar/lobby/team/TeamPlayer.java new file mode 100644 index 0000000..047c69a --- /dev/null +++ b/src/de/steamwar/lobby/team/TeamPlayer.java @@ -0,0 +1,117 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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 . + */ + +package de.steamwar.lobby.team; + +import de.steamwar.lobby.LobbySystem; +import de.steamwar.lobby.display.NPC; +import de.steamwar.lobby.listener.BasicListener; +import de.steamwar.sql.SteamwarUser; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityInteractEvent; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.HashMap; +import java.util.Map; + +public class TeamPlayer extends BasicListener { + + private static Map entities = new HashMap<>(); + + public static void spawnTeamPlayer(World world, String name) { + Location location = new Location(world, 1524.5, 52, 1493.5); + NPC npc = new NPC(location, SteamwarUser.get(name).getUUID(), name); + Villager villager = (Villager) world.spawnEntity(location, EntityType.VILLAGER); + villager.setSilent(true); + villager.setInvulnerable(true); + villager.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, Integer.MAX_VALUE, 1, false, false, false)); + villager.setCustomName(name); + villager.setProfession(Villager.Profession.NITWIT); + entities.put(villager, npc); + } + + public static void cleanup() { + entities.forEach((entity, npc) -> entity.remove()); + } + + { + World world = Bukkit.getWorld("Lobby"); + for (int x = -10; x < 10; x++) { + for (int z = -10; z < 10; z++) { + world.setChunkForceLoaded(95 + x , 93 + z, true); + } + } + world.getEntitiesByClasses(Villager.class).forEach(Entity::remove); + for (int x = -10; x < 10; x++) { + for (int z = -10; z < 10; z++) { + world.setChunkForceLoaded(95 + x , 93 + z, true); + } + } + spawnTeamPlayer(world, "AdmiralSeekrank"); + spawnTeamPlayer(world, "SalzgehaltSensei"); + spawnTeamPlayer(world, "Sehfxhler"); + spawnTeamPlayer(world, "Tim7077"); + spawnTeamPlayer(world, "LordMainex"); + spawnTeamPlayer(world, "Lixi266"); + spawnTeamPlayer(world, "PxlPain"); + spawnTeamPlayer(world, "KopFilme"); + spawnTeamPlayer(world, "Lixfel"); + spawnTeamPlayer(world, "Chaoscaot"); + spawnTeamPlayer(world, "YoyoNow"); + spawnTeamPlayer(world, "Zeanon"); + spawnTeamPlayer(world, "zOnlyKroks"); + spawnTeamPlayer(world, "Legula"); + spawnTeamPlayer(world, "xJoul"); + spawnTeamPlayer(world, "Maybe_Creative"); + spawnTeamPlayer(world, "Tim16227"); + spawnTeamPlayer(world, "FoehnX"); + spawnTeamPlayer(world, "_Noerf_"); + spawnTeamPlayer(world, "Edmund_Strong"); + spawnTeamPlayer(world, "TheBreadBeard"); + spawnTeamPlayer(world, "Basic_Redstone"); + + Bukkit.getScheduler().runTaskTimer(LobbySystem.getPlugin(), () -> { + entities.forEach((entity, npc) -> { + npc.setLocation(entity.getLocation()); + }); + }, 1L, 1L); + } + + @EventHandler + public void onEntityInteract(EntityInteractEvent event) { + if (event.getEntityType() == EntityType.VILLAGER) { + event.setCancelled(true); + } + } + + @EventHandler + public void onEntityDamage(EntityDamageEvent event) { + if (event.getEntityType() == EntityType.VILLAGER) { + event.setCancelled(true); + } + } +}