diff --git a/FightSystem_14/src/de/steamwar/fightsystem/utils/WaterRemover_14.java b/FightSystem_14/src/de/steamwar/fightsystem/utils/WaterRemover_14.java index 265d2e3..17260c3 100644 --- a/FightSystem_14/src/de/steamwar/fightsystem/utils/WaterRemover_14.java +++ b/FightSystem_14/src/de/steamwar/fightsystem/utils/WaterRemover_14.java @@ -37,4 +37,24 @@ class WaterRemover_14 { return ((Waterlogged) data).isWaterlogged(); } + + static boolean removeWater(Block block){ + if(block.getType() == Material.WATER){ + block.setType(Material.AIR); + return true; + } + + BlockData data = block.getBlockData(); + if(!(data instanceof Waterlogged)) + return false; + + Waterlogged waterlogged = (Waterlogged) data; + if(waterlogged.isWaterlogged()){ + waterlogged.setWaterlogged(false); + block.setBlockData(waterlogged); + return true; + } + + return false; + } } diff --git a/FightSystem_15/src/de/steamwar/fightsystem/record/RecordSystem_15.java b/FightSystem_15/src/de/steamwar/fightsystem/record/RecordSystem_15.java new file mode 100644 index 0000000..6d1a1e3 --- /dev/null +++ b/FightSystem_15/src/de/steamwar/fightsystem/record/RecordSystem_15.java @@ -0,0 +1,31 @@ +/* + 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 . +*/ + +package de.steamwar.fightsystem.record; + +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_15_R1.block.CraftBlock; + +class RecordSystem_15 { + private RecordSystem_15(){} + + static int blockToId(Block block){ + return net.minecraft.server.v1_15_R1.Block.REGISTRY_ID.getId(((CraftBlock)block).getNMS()); + } +} diff --git a/FightSystem_8/src/de/steamwar/fightsystem/record/RecordSystem_8.java b/FightSystem_8/src/de/steamwar/fightsystem/record/RecordSystem_8.java new file mode 100644 index 0000000..207a3fd --- /dev/null +++ b/FightSystem_8/src/de/steamwar/fightsystem/record/RecordSystem_8.java @@ -0,0 +1,31 @@ +/* + 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 . +*/ + +package de.steamwar.fightsystem.record; + +import org.bukkit.block.Block; + +class RecordSystem_8 { + private RecordSystem_8(){} + + @SuppressWarnings("deprecation") + static int blockToId(Block block){ + return block.getTypeId() << 4 + block.getData(); + } +} diff --git a/FightSystem_8/src/de/steamwar/fightsystem/utils/WaterRemover_8.java b/FightSystem_8/src/de/steamwar/fightsystem/utils/WaterRemover_8.java index 0a544df..a510557 100644 --- a/FightSystem_8/src/de/steamwar/fightsystem/utils/WaterRemover_8.java +++ b/FightSystem_8/src/de/steamwar/fightsystem/utils/WaterRemover_8.java @@ -29,4 +29,12 @@ public class WaterRemover_8 { Material type = block.getType(); return type == Material.WATER || type == Material.STATIONARY_WATER; } + + static boolean removeWater(Block block){ + if(isWater(block)){ + block.setType(Material.AIR); + return true; + } + return false; + } } diff --git a/FightSystem_API/src/de/steamwar/fightsystem/Config.java b/FightSystem_API/src/de/steamwar/fightsystem/Config.java index 43db7ba..524da67 100644 --- a/FightSystem_API/src/de/steamwar/fightsystem/Config.java +++ b/FightSystem_API/src/de/steamwar/fightsystem/Config.java @@ -140,10 +140,15 @@ public class Config { public static final int EventTeamRedID; public static final boolean BothTeamsPublic; public static final int MaximumTeamMembers; + public static final boolean SpectateSystem; //check parameter public static final int CheckSchemID; + //live recorder parameter + public static final String spectateIP = "127.0.0.1"; + public static final int spectatePort = 2222; + static{ File worldConfigFile = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "config.yml"); if(!worldConfigFile.exists()) { @@ -370,6 +375,7 @@ public class Config { OnlyPublicSchematics = event.publicSchemsOnly(); MaximumTeamMembers = event.getMaximumTeamMembers(); } + SpectateSystem = event.spectateSystem(); }else{ //No event TeamRedName = config.getString("Output.TeamRedName"); @@ -379,6 +385,7 @@ public class Config { EventTeamRedID = 0; BothTeamsPublic = true; MaximumTeamMembers = Integer.MAX_VALUE; + SpectateSystem = false; } String blueLeader = System.getProperty("blueLeader", null); @@ -405,4 +412,7 @@ public class Config { public static boolean check(){ return CheckSchemID != 0; } + public static boolean recording(){ + return event(); + } } diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem_Main/src/de/steamwar/fightsystem/FightSystem.java index 4c7e65f..8ad4146 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/FightSystem.java @@ -28,9 +28,14 @@ import de.steamwar.fightsystem.fight.FightPlayer; import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.kit.KitManager; import de.steamwar.fightsystem.listener.*; +import de.steamwar.fightsystem.record.RecordSystem; +import de.steamwar.fightsystem.record.Recorder; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.StateDependent; -import de.steamwar.fightsystem.utils.*; +import de.steamwar.fightsystem.utils.EnterHandler; +import de.steamwar.fightsystem.utils.FightScoreboard; +import de.steamwar.fightsystem.utils.FightStatistics; +import de.steamwar.fightsystem.utils.TechHider; import de.steamwar.fightsystem.winconditions.*; import de.steamwar.sql.EventFight; import de.steamwar.sql.Schematic; @@ -66,6 +71,7 @@ public class FightSystem extends JavaPlugin { KitManager.loadAllKits(); TechHider.init(); FightScoreboard.init(); + RecordSystem.init(); try { CommandRemover.removeAll("gamemode"); @@ -89,6 +95,7 @@ public class FightSystem extends JavaPlugin { new InFightInventoryListener(); new FreezeWorldStateListener(); new EventJoinListener(); + new EventRecordListener(); new CheckListener(); new TestListener(); new NormalJoinListener(); @@ -144,6 +151,12 @@ public class FightSystem extends JavaPlugin { } } + @Override + public void onDisable() { + + Recorder.closeAll(); + } + public static void setPreSchemState() { if(fightState != FightState.PRE_LEADER_SETUP) throw new SecurityException(fightState.name()); diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/commands/GUI.java b/FightSystem_Main/src/de/steamwar/fightsystem/commands/GUI.java index 7d598ba..fe567c3 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/commands/GUI.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/commands/GUI.java @@ -153,7 +153,8 @@ public class GUI { FightTeam fightTeam = Fight.getPlayerTeam(p); if(fightTeam == null) return; - fightTeam.setSchematic(s); + if(FightSystem.getFightState() != FightState.POST_SCHEM_SETUP) + fightTeam.setSchematic(s); p.closeInventory(); }); inv.setCallback(-999, (ClickType click) -> p.closeInventory()); diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/countdown/Countdown.java b/FightSystem_Main/src/de/steamwar/fightsystem/countdown/Countdown.java index 7b1c2fe..6618edd 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/countdown/Countdown.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/countdown/Countdown.java @@ -20,9 +20,11 @@ package de.steamwar.fightsystem.countdown; import de.steamwar.core.Core; +import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.listener.BasicListener; +import de.steamwar.fightsystem.record.RecordSystem; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; @@ -71,6 +73,8 @@ public abstract class Countdown { } private void broadcast(String message){ + if(Config.recording()) + RecordSystem.actionBar(message); BaseComponent[] msg = TextComponent.fromLegacyText(message); for(Player p : Bukkit.getOnlinePlayers()) BasicListener.toActionbar(p, msg); diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/fight/Fight.java b/FightSystem_Main/src/de/steamwar/fightsystem/fight/Fight.java index 4f4d4ca..e060c46 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/fight/Fight.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/fight/Fight.java @@ -19,15 +19,24 @@ package de.steamwar.fightsystem.fight; +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.EnumWrappers; +import com.comphenix.protocol.wrappers.PlayerInfoData; +import com.comphenix.protocol.wrappers.WrappedChatComponent; +import com.comphenix.protocol.wrappers.WrappedGameProfile; import de.steamwar.fightsystem.Config; +import de.steamwar.fightsystem.record.RecordSystem; +import de.steamwar.fightsystem.FightSystem; import de.steamwar.sql.Schematic; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Material; -import org.bukkit.Sound; +import org.bukkit.*; import org.bukkit.entity.Player; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; public class Fight { private Fight(){} @@ -84,6 +93,8 @@ public class Fight { } public static void playSound(Sound sound, float volume, float pitch) { + if(Config.recording()) + RecordSystem.soundAtPlayer(sound.name(), volume, pitch); //volume: max. 100, pitch: max. 2 Bukkit.getServer().getOnlinePlayers().forEach(player -> player.playSound(player.getLocation(), sound, volume, pitch)); } @@ -114,17 +125,33 @@ public class Fight { if(gameMode == GameMode.SPECTATOR) { for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) { - currentPlayer.hidePlayer(player); - player.hidePlayer(currentPlayer); + currentPlayer.hidePlayer(FightSystem.getPlugin(), player); + player.hidePlayer(FightSystem.getPlugin(), currentPlayer); } } - } - if(gameMode == GameMode.SURVIVAL) { + if(FightSystem.getEventLeiter() == player || Config.test()) + return; + + Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> { + if(!player.isOnline()) + return; + PacketContainer gm1packet = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.PLAYER_INFO); + gm1packet.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE); + List playerInfoActions = new ArrayList<>(); + playerInfoActions.add(new PlayerInfoData(WrappedGameProfile.fromPlayer(player), 1, EnumWrappers.NativeGameMode.CREATIVE, WrappedChatComponent.fromText(player.getDisplayName()))); + gm1packet.getPlayerInfoDataLists().write(0, playerInfoActions); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(player, gm1packet); + } catch (InvocationTargetException e) { + Bukkit.getLogger().log(Level.SEVERE, "Invocation target exception", e); + } + }, 2); + }else if(gameMode == GameMode.SURVIVAL) { for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) { - currentPlayer.showPlayer(player); - player.showPlayer(currentPlayer); + currentPlayer.showPlayer(FightSystem.getPlugin(), player); + player.showPlayer(FightSystem.getPlugin(), currentPlayer); } } } diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/fight/FightTeam.java b/FightSystem_Main/src/de/steamwar/fightsystem/fight/FightTeam.java index 6bd4a93..57380a2 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/fight/FightTeam.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/fight/FightTeam.java @@ -20,13 +20,19 @@ package de.steamwar.fightsystem.fight; import com.sk89q.worldedit.EditSession; +import de.steamwar.comms.packets.TablistNamePacket; import de.steamwar.core.Core; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.IFightSystem; import de.steamwar.fightsystem.kit.KitManager; +import de.steamwar.fightsystem.listener.PersonalKitCreator; +import de.steamwar.fightsystem.record.RecordSystem; import de.steamwar.fightsystem.states.FightState; -import de.steamwar.fightsystem.utils.*; +import de.steamwar.fightsystem.utils.ColorConverter; +import de.steamwar.fightsystem.utils.FightScoreboard; +import de.steamwar.fightsystem.utils.ItemBuilder; +import de.steamwar.fightsystem.utils.TechHider; import de.steamwar.fightsystem.winconditions.RankedPlayerLeftWincondition; import de.steamwar.inventory.SWItem; import de.steamwar.sql.NoClipboardException; @@ -177,6 +183,10 @@ public class FightTeam implements IFightTeam{ if(KitManager.getKits(false).size() > 1 || Config.PersonalKits) player.getInventory().setItem(1, new ItemBuilder(Material.LEATHER_CHESTPLATE).removeAllAttributs().addEnchantment(Enchantment.DURABILITY, 1).setDisplayName("§eKit wählen").build()); player.getInventory().setItem(7, new ItemBuilder(Material.BEACON).removeAllAttributs().setDisplayName("§eRespawn").build()); + if(!Config.test()) + Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> new TablistNamePacket(SteamwarUser.get(player.getUniqueId()).getId(), prefix + player.getName()).send(player), 5); + if(Config.recording()) + RecordSystem.playerJoins(player); TechHider.reloadChunks(player, chunksToReload); return fightPlayer; } @@ -194,6 +204,10 @@ public class FightTeam implements IFightTeam{ Fight.setPlayerGamemode(player, GameMode.SPECTATOR); player.teleport(Config.SpecSpawn); + if(!Config.test()) + new TablistNamePacket(SteamwarUser.get(player.getUniqueId()).getId(), "§7§o" + player.getName()).send(player); + if(Config.recording()) + RecordSystem.entityDespawns(player); TechHider.reloadChunks(player, chunksToReload); } @@ -222,6 +236,9 @@ public class FightTeam implements IFightTeam{ } return; } + if (!PersonalKitCreator.notInKitCreator(leader.getPlayer())) + leader.getPlayer().closeInventory(); + this.leader = leader; if(ready) setReady(false); @@ -255,6 +272,13 @@ public class FightTeam implements IFightTeam{ } public void pasteSchematic(){ + if(Config.recording()){ + if(blue) + RecordSystem.blueSchem(schematic); + else + RecordSystem.redSchem(schematic); + } + FreezeWorld freezer = new FreezeWorld(); DyeColor c = ColorConverter.chat2dye(color); Schematic schem; diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/listener/EventJoinListener.java b/FightSystem_Main/src/de/steamwar/fightsystem/listener/EventJoinListener.java index 23a4a31..6e60e5c 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/listener/EventJoinListener.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/listener/EventJoinListener.java @@ -29,6 +29,7 @@ import de.steamwar.sql.SteamwarUser; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; import java.util.EnumSet; @@ -39,6 +40,21 @@ public class EventJoinListener extends BasicListener { super(Config.event() ? EnumSet.of(FightState.PRE_LEADER_SETUP, FightState.PRE_SCHEM_SETUP, FightState.POST_SCHEM_SETUP) : EnumSet.noneOf(FightState.class)); } + @EventHandler + public void playerLogin(PlayerLoginEvent event) { + if(!Config.SpectateSystem) + return; + + Player player = event.getPlayer(); + SteamwarUser user = SteamwarUser.get(player.getUniqueId()); + if(user.getTeam() == Config.EventTeamBlueID || + user.getTeam() == Config.EventTeamRedID || + user.getId() == FightSystem.getEventFight().getKampfleiter()) + return; + + event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "§cDu bist kein Kampfteilnehmer"); + } + @EventHandler public void handlePlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); @@ -66,10 +82,15 @@ public class EventJoinListener extends BasicListener { FightPlayer fp = team.addMember(player); if(!team.hasTeamLeader()) team.setLeader(fp); + return; } - if(user.getId() == FightSystem.getEventFight().getKampfleiter()) + if(user.getId() == FightSystem.getEventFight().getKampfleiter()){ FightSystem.setEventLeiter(player); + return; + } + if(Config.SpectateSystem) + player.kickPlayer("§cDu bist kein Kampfteilnehmer"); } @EventHandler diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/listener/EventRecordListener.java b/FightSystem_Main/src/de/steamwar/fightsystem/listener/EventRecordListener.java new file mode 100644 index 0000000..7b690a1 --- /dev/null +++ b/FightSystem_Main/src/de/steamwar/fightsystem/listener/EventRecordListener.java @@ -0,0 +1,227 @@ +/* + 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 . +*/ + +package de.steamwar.fightsystem.listener; + +import de.steamwar.fightsystem.Config; +import de.steamwar.fightsystem.FightSystem; +import de.steamwar.fightsystem.fight.Fight; +import de.steamwar.fightsystem.fight.FightPlayer; +import de.steamwar.fightsystem.fight.FightTeam; +import de.steamwar.fightsystem.record.RecordSystem; +import de.steamwar.fightsystem.states.FightState; +import org.bukkit.*; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.entity.ProjectileLaunchEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.event.player.*; +import org.bukkit.event.server.BroadcastMessageEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.EnumSet; +import java.util.Random; + +public class EventRecordListener extends BasicListener { + + private static final int AIR = 0; + private static final Random random = new Random(); + + public EventRecordListener() { + super(Config.recording() ? EnumSet.allOf(FightState.class) : EnumSet.noneOf(FightState.class)); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerMove(PlayerMoveEvent e){ + if(isNotSent(e.getPlayer())) + return; + + RecordSystem.entityMoves(e.getPlayer()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerDeath(PlayerDeathEvent e){ + if(isNotSent(e.getEntity())) + return; + + RecordSystem.entityDespawns(e.getEntity()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBroadcast(BroadcastMessageEvent e){ + RecordSystem.systemChat(e.getMessage()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onSneak(PlayerToggleSneakEvent e){ + if(isNotSent(e.getPlayer())) + return; + + RecordSystem.playerSneak(e.getPlayer(), e.isSneaking()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onAnimation(PlayerAnimationEvent e){ + if(isNotSent(e.getPlayer())) + return; + + if(e.getAnimationType() == PlayerAnimationType.ARM_SWING) + RecordSystem.entityAnimation(e.getPlayer(), AIR); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onTNTSpawn(EntitySpawnEvent e){ + //TODO: Falling block + if(e.getEntityType() != EntityType.PRIMED_TNT) + return; + + RecordSystem.tntSpawn(e.getEntity()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockPhysics(BlockPhysicsEvent e){ + if(e.getBlock() == e.getSourceBlock() || e.getChangedType() == Material.AIR) + RecordSystem.blockChange(e.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onExplosion(EntityExplodeEvent e){ + if(e.getEntityType() != EntityType.PRIMED_TNT) + return; + + Location loc = e.getLocation(); + RecordSystem.entityDespawns(e.getEntity()); + RecordSystem.particle(loc.getX(), loc.getY(), loc.getZ(), Particle.EXPLOSION_HUGE.name()); + RecordSystem.sound(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), Sound.ENTITY_GENERIC_EXPLODE.name(), SoundCategory.BLOCKS.name(), 4.0F, (1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F) * 0.7F); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onItem(PlayerItemHeldEvent e){ + if(isNotSent(e.getPlayer())) + return; + + RecordSystem.item(e.getPlayer(), disarmNull(e.getPlayer().getInventory().getItem(e.getNewSlot())), "MAINHAND"); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onItemSwap(PlayerSwapHandItemsEvent e){ + if(isNotSent(e.getPlayer())) + return; + + Player player = e.getPlayer(); + RecordSystem.item(player, disarmNull(e.getMainHandItem()), "MAINHAND"); + RecordSystem.item(player, disarmNull(e.getOffHandItem()), "OFFHAND"); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onProjectileSpawn(ProjectileLaunchEvent e){ + if(e.getEntityType() == EntityType.FIREBALL) + RecordSystem.fireballSpawn(e.getEntity()); + else if(e.getEntityType() == EntityType.ARROW) + RecordSystem.arrowSpawn(e.getEntity()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onInventoryClick(InventoryClickEvent e){ + Player player = (Player) e.getWhoClicked(); + if(isNotSent(player)) + return; + + if(e.getSlotType() != InventoryType.SlotType.ARMOR) + return; + + switch(e.getSlot()){ + case 103: + RecordSystem.item(player, disarmNull(e.getCurrentItem()), "HEAD"); + break; + case 102: + RecordSystem.item(player, disarmNull(e.getCurrentItem()), "CHEST"); + break; + case 101: + RecordSystem.item(player, disarmNull(e.getCurrentItem()), "LEGS"); + break; + case 100: + default: + RecordSystem.item(player, disarmNull(e.getCurrentItem()), "FEET"); + } + } + + @Override + public void stateChange(FightState state) { + if(state == FightState.PRE_RUNNING) { + Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> { + setKitItems(Fight.getBlueTeam()); + setKitItems(Fight.getRedTeam()); + }, 1); + }else if(state == FightState.SPECTATE){ + despawnTeam(Fight.getRedTeam()); + despawnTeam(Fight.getBlueTeam()); + despawnTNT(); + } + } + + private void setKitItems(FightTeam team){ + if(FightSystem.getFightState() != FightState.PRE_RUNNING) + return; + + for(FightPlayer fp : team.getPlayers()){ + if(!fp.isLiving()) + continue; + + Player player = fp.getPlayer(); + RecordSystem.item(player, disarmNull(player.getInventory().getItemInMainHand()), "MAINHAND"); + RecordSystem.item(player, disarmNull(player.getInventory().getItemInOffHand()), "OFFHAND"); + RecordSystem.item(player, disarmNull(player.getInventory().getHelmet()), "HEAD"); + RecordSystem.item(player, disarmNull(player.getInventory().getChestplate()), "CHEST"); + RecordSystem.item(player, disarmNull(player.getInventory().getLeggings()), "LEGS"); + RecordSystem.item(player, disarmNull(player.getInventory().getBoots()), "FEET"); + } + } + + private ItemStack disarmNull(ItemStack stack){ + if(stack == null) + return new ItemStack(Material.AIR); + return stack; + } + + private void despawnTeam(FightTeam team){ + for(FightPlayer player : team.getPlayers()){ + if(player.isLiving()) + RecordSystem.entityDespawns(player.getPlayer()); + } + } + + private void despawnTNT(){ + for(TNTPrimed tnt : Bukkit.getWorlds().get(0).getEntitiesByClass(TNTPrimed.class)) + RecordSystem.entityDespawns(tnt); + } + + private boolean isNotSent(Player p){ + FightPlayer fp = Fight.getFightPlayer(p); + return fp == null || !fp.isLiving() || FightSystem.getFightState() == FightState.SPECTATE; + } +} diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/listener/PersonalKitCreator.java b/FightSystem_Main/src/de/steamwar/fightsystem/listener/PersonalKitCreator.java index c593dae..104fa81 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/listener/PersonalKitCreator.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/listener/PersonalKitCreator.java @@ -78,7 +78,7 @@ public class PersonalKitCreator extends BasicListener { player.setGameMode(GameMode.CREATIVE); } - static boolean notInKitCreator(HumanEntity player){ + public static boolean notInKitCreator(HumanEntity player){ return !openKitCreators.containsKey(player); } diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerChatListener.java b/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerChatListener.java index c627ad0..394f109 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerChatListener.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerChatListener.java @@ -23,6 +23,7 @@ import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightTeam; +import de.steamwar.fightsystem.record.RecordSystem; import de.steamwar.fightsystem.states.FightState; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; @@ -61,7 +62,9 @@ public class PlayerChatListener extends BasicListener { event.setCancelled(true); } - private void broadcastChat(String message){ + private void broadcastChat(String message) { + if (Config.recording()) + RecordSystem.chat(message); BaseComponent[] msg = TextComponent.fromLegacyText(message); for(Player p : Bukkit.getOnlinePlayers()) toChat(p, msg); diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerMoveListener.java b/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerMoveListener.java index d6b678e..bec0121 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerMoveListener.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerMoveListener.java @@ -26,6 +26,7 @@ import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.utils.Region; import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -33,6 +34,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerMoveEvent; import java.util.EnumSet; +import java.util.logging.Level; public class PlayerMoveListener extends BasicListener { @@ -64,15 +66,30 @@ public class PlayerMoveListener extends BasicListener { reset(event, DENY_TEAM); else if(fightTeam == Fight.getRedTeam() && player.getGameMode() == GameMode.SPECTATOR) reset(event, DENY_ENTERN); + else + return; // Is allowed in area + checkInInnerArea(event.getPlayer(), to, Config.TeamBlueCornerX, Config.TeamBlueCornerZ); }else if(inRedArea){ if(fightTeam == null) reset(event, DENY_TEAM); else if(fightTeam == Fight.getBlueTeam() && player.getGameMode() == GameMode.SPECTATOR) reset(event, DENY_ENTERN); + else + return; // Is allowed in area + checkInInnerArea(event.getPlayer(), to, Config.TeamRedCornerX, Config.TeamRedCornerZ); }else if(fightTeam != null && player.getGameMode() != GameMode.SPECTATOR && !fightTeam.canPlayerEntern(player)) reset(event, DENY_ENTERN); } + private void checkInInnerArea(Player player, Location to, int teamCornerX, int teamCornerZ){ + boolean inArenaY = to.getY() + 1.8 <= Config.TeamBlueCornerY + Config.SchemsizeY; + boolean inArea = inArenaY && Region.isIn2DRange(to, teamCornerX, teamCornerZ, Config.SchemsizeX, Config.SchemsizeZ, 0); + if(inArea){ + player.kickPlayer(null); + Bukkit.getLogger().log(Level.SEVERE, player.getName() + " ist in einen Teambereich eingedrungen."); + } + } + @EventHandler public void arenaBorder(PlayerMoveEvent event){ Player player = event.getPlayer(); diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerStateListener.java b/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerStateListener.java index 8f179e6..3830c12 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerStateListener.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/listener/PlayerStateListener.java @@ -19,6 +19,7 @@ package de.steamwar.fightsystem.listener; +import de.steamwar.comms.packets.TablistNamePacket; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.countdown.Countdown; @@ -26,7 +27,9 @@ import de.steamwar.fightsystem.countdown.SWSound; import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightPlayer; import de.steamwar.fightsystem.fight.FightTeam; +import de.steamwar.fightsystem.record.RecordSystem; import de.steamwar.fightsystem.states.FightState; +import de.steamwar.sql.SteamwarUser; import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.GameMode; @@ -61,6 +64,8 @@ public class PlayerStateListener extends BasicListener{ if (fightTeam == null) { Fight.setPlayerGamemode(player, GameMode.SPECTATOR); player.teleport(Config.SpecSpawn); + if(!Config.test()) + Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> new TablistNamePacket(SteamwarUser.get(player.getUniqueId()).getId(), "§7" + player.getName()).send(player), 5); } else { player.teleport(fightTeam.getSpawn()); if(FightSystem.getFightState().setup()) @@ -85,6 +90,8 @@ public class PlayerStateListener extends BasicListener{ Fight.setPlayerGamemode(player, GameMode.SPECTATOR); player.teleport(fightTeam.getSpawn()); Fight.playSound(Countdown.getSound(SWSound.ENTITY_WITHER_DEATH), 100.0F, 1.0F); + if(Config.recording()) + RecordSystem.entityDespawns(player); } @EventHandler(priority = EventPriority.HIGH) @@ -99,11 +106,17 @@ public class PlayerStateListener extends BasicListener{ FightState fightState = FightSystem.getFightState(); if(fightState.setup()){ fightTeam.removePlayer(player); + + if(Config.recording()) + RecordSystem.entityDespawns(player); }else if(fightState.ingame()){ FightPlayer fightPlayer = fightTeam.getFightPlayer(player); if(fightPlayer.isLiving()) { Bukkit.broadcastMessage(FightSystem.PREFIX + "§cDer Spieler " + fightTeam.getPrefix() + player.getName() + " §chat den Kampf verlassen!"); fightTeam.getFightPlayer(player).setOut(); + + if(Config.recording()) + RecordSystem.entityDespawns(player); } } diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/record/FileRecorder.java b/FightSystem_Main/src/de/steamwar/fightsystem/record/FileRecorder.java new file mode 100644 index 0000000..3a0c616 --- /dev/null +++ b/FightSystem_Main/src/de/steamwar/fightsystem/record/FileRecorder.java @@ -0,0 +1,146 @@ +/* + 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 . +*/ + +package de.steamwar.fightsystem.record; + +import org.bukkit.Bukkit; +import org.bukkit.World; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.logging.Level; +import java.util.zip.GZIPOutputStream; + +public class FileRecorder extends Recorder { + + private final DataOutputStream outputStream; + + public FileRecorder(){ + super(); + World world = Bukkit.getWorlds().get(0); + File file = new File(world.getWorldFolder(), world.getName() + ".recording"); + try{ + file.createNewFile(); + outputStream = new DataOutputStream(new GZIPOutputStream(new FileOutputStream(file), 4096)); + }catch(IOException e){ + throw new SecurityException("Could not open file", e); + } + } + + @Override + protected void writeBoolean(boolean b) { + try { + outputStream.writeBoolean(b); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not write", e); + close(); + } + } + + @Override + protected void writeByte(int b) { + try { + outputStream.writeByte(b); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not write", e); + close(); + } + } + + @Override + protected void writeShort(short s) { + try { + outputStream.writeShort(s); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not write", e); + close(); + } + } + + @Override + protected void writeInt(int i) { + try { + outputStream.writeInt(i); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not write", e); + close(); + } + } + + @Override + protected void writeLong(long l) { + try { + outputStream.writeLong(l); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not write", e); + close(); + } + } + + @Override + protected void writeFloat(float f) { + try { + outputStream.writeFloat(f); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not write", e); + close(); + } + } + + @Override + protected void writeDouble(double d) { + try { + outputStream.writeDouble(d); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not write", e); + close(); + } + } + + @Override + protected void writeString(String s) { + try { + outputStream.writeUTF(s); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not write", e); + close(); + } + } + + @Override + protected void doFlush() { + try { + outputStream.flush(); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not flush", e); + close(); + } + } + + @Override + protected void closeRecorder() { + try { + outputStream.close(); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not close OutputStream", e); + } + } +} diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/record/RecordSystem.java b/FightSystem_Main/src/de/steamwar/fightsystem/record/RecordSystem.java new file mode 100644 index 0000000..84660b4 --- /dev/null +++ b/FightSystem_Main/src/de/steamwar/fightsystem/record/RecordSystem.java @@ -0,0 +1,303 @@ +/* + 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 . +*/ + +package de.steamwar.fightsystem.record; + +import de.steamwar.core.Core; +import de.steamwar.fightsystem.Config; +import de.steamwar.fightsystem.FightSystem; +import de.steamwar.fightsystem.states.FightState; +import de.steamwar.sql.SteamwarUser; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_15_R1.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +public class RecordSystem { + private RecordSystem(){} + + private static final World WORLD = Bukkit.getWorlds().get(0); + + public static void init(){ + if(!Config.recording()) + return; + + Bukkit.getScheduler().runTaskTimer(FightSystem.getPlugin(), RecordSystem::checkWorldState, 1, 1); + new SpectateConnection(); + new FileRecorder(); + if(Config.event()) + teamIds(Config.EventTeamBlueID, Config.EventTeamRedID); + } + + /* + * PlayerJoinPacket (0x00) + int EntityId + int SWUserId + * EntityMovePacket (0x01) + int EntityId + double x, y, z + float pitch, yaw + byte headyaw + * EntityDespawnsPacket (0x02) + int EntityId + * PlayerSneakPacket (0x03) + int EntityId + boolean sneaks + * EntityAnimationPacket (0x04) + int EntityId + byte animation + * TNTSpawnPacket (0x05) + int EntityId + * EntitySpeedPacket (0x06) + int EntityId + double dx, dy, dz + * PlayerItemPacket (0x07) + int EntityId + String item + boolean enchanted + String slot + * ArrowSpawnPacket (0x08) + int EntityId + * FireballSpawnPacket (0x09) + int EntityId + * TODO Bow spanning + * + * + * + * BlockPacket (0x30) + pos int, byte, int + int BlockState + * ParticlePacket (0x31) + double x, y, z + string particleType + * SoundPacket (0x32) + int x, y, z + string soundType + string soundCategory + float volume, pitch + * ShortBlockPacket (0x33) + pos relative to ArenaMinX,ArenaMinZ byte, byte, byte + short BlockState + * SoundAtPlayerPacket (0x34) + string (soundType, soundCategory) + float volume, pitch + * + * + * ChatPacket (0xA0) + String message + * ActionBarPacket (0xA1) + String message + * SystemPacket (0xA2) + String message + * BlueSchemPacket (0xB0) + int blueSchemId + * RedSchemPacket (0xB1) + int redSchemId + * TeamIDPacket (0xB2) + int blueTeamId, redTeamId + * ScoreboardTitlePacket (0xC0) + String scoreboardTitle + * ScoreboardDataPacket (0xC1) + String key + int value + * + * CommentPacket (0xfe) + String comment + * TickPacket (0xff) + * */ + + public static synchronized void playerJoins(Player p){ + SteamwarUser user = SteamwarUser.get(p.getUniqueId()); + + Recorder.rByte(0x00); + Recorder.rInt(p.getEntityId()); + Recorder.rInt(user.getId()); + entityMoves(p); + } + + public static synchronized void entityMoves(Entity e){ + Location location = e.getLocation(); + + Recorder.rByte(0x01); + Recorder.rInt(e.getEntityId()); + Recorder.rDouble(location.getX()); + Recorder.rDouble(location.getY()); + Recorder.rDouble(location.getZ()); + Recorder.rFloat(location.getPitch()); + Recorder.rFloat(location.getYaw()); + Recorder.rByte((int)(((CraftEntity)e).getHandle().getHeadRotation() * 256 / 360)); + Recorder.flush(); + } + + public static synchronized void entityDespawns(Entity e){ + Recorder.rByte(0x02); + Recorder.rInt(e.getEntityId()); + Recorder.flush(); + } + + public static synchronized void playerSneak(Player p, boolean sneaks){ + Recorder.rByte(0x03); + Recorder.rInt(p.getEntityId()); + Recorder.rBoolean(sneaks); + Recorder.flush(); + } + + public static synchronized void entityAnimation(Entity e, int animation){ + Recorder.rByte(0x04); + Recorder.rInt(e.getEntityId()); + Recorder.rByte(animation); + Recorder.flush(); + } + + public static synchronized void tntSpawn(Entity e){ + Recorder.rByte(0x05); + spawnEntity(e); + } + + public static synchronized void entitySpeed(Entity e){ + Vector velocity = e.getVelocity(); + Recorder.rByte(0x06); + Recorder.rInt(e.getEntityId()); + Recorder.rDouble(velocity.getX()); + Recorder.rDouble(velocity.getY()); + Recorder.rDouble(velocity.getZ()); + Recorder.flush(); + } + + public static synchronized void item(Player p, ItemStack item, String slot){ + Recorder.rByte(0x07); + Recorder.rInt(p.getEntityId()); + Recorder.rString(item.getType().getKey().toString()); + Recorder.rBoolean(!item.getEnchantments().isEmpty()); + Recorder.rString(slot); + Recorder.flush(); + } + + public static synchronized void arrowSpawn(Entity e){ + Recorder.rByte(0x08); + spawnEntity(e); + } + + public static synchronized void fireballSpawn(Entity e){ + Recorder.rByte(0x09); + spawnEntity(e); + } + + public static synchronized void blockChange(Block block){ + int blockState = blockToId(block); + + int shortX = block.getX() - Config.ArenaMinX; + int shortZ = block.getZ() - Config.ArenaMinZ; + if((short)blockState == blockState && shortX > 0 && shortX < 256 && shortZ > 0 && shortZ < 256){ + //Short block packet + Recorder.rByte(0x33); + Recorder.rByte(shortX); + Recorder.rByte(block.getY()); + Recorder.rByte(shortZ); + Recorder.rShort((short)blockState); + }else{ + //Block packet + Recorder.rByte(0x30); + Recorder.rInt(block.getX()); + Recorder.rByte(block.getY()); + Recorder.rInt(block.getZ()); + Recorder.rInt(blockState); + } + Recorder.flush(); + } + + public static synchronized void particle(double x, double y, double z, String particleType){ + Recorder.rByte(0x31); + Recorder.rDouble(x); + Recorder.rDouble(y); + Recorder.rDouble(z); + Recorder.rString(particleType); + Recorder.flush(); + } + + public static synchronized void sound(int x, int y, int z, String soundType, String soundCategory, float volume, float pitch){ + Recorder.rByte(0x32); + Recorder.rInt(x); + Recorder.rInt(y); + Recorder.rInt(z); + Recorder.rString(soundType); + Recorder.rString(soundCategory); + Recorder.rFloat(volume); + Recorder.rFloat(pitch); + Recorder.flush(); + } + + public static synchronized void soundAtPlayer(String soundType, float volume, float pitch){ + Recorder.rByte(0x34); + Recorder.rString(soundType); + Recorder.rFloat(volume); + Recorder.rFloat(pitch); + Recorder.flush(); + } + + public static synchronized void chat(String s) { + Recorder.rByte(0xA0); + Recorder.rString(s); + Recorder.flush(); + } + + public static synchronized void actionBar(String s) { + Recorder.rByte(0xA1); + Recorder.rString(s); + Recorder.flush(); + } + + public static synchronized void systemChat(String s) { + Recorder.rByte(0xA2); + Recorder.rString(s); + Recorder.flush(); + } + + public static synchronized void blueSchem(int schemId) { + Recorder.rByte(0xB0); + Recorder.rInt(schemId); + Recorder.flush(); + } + + public static synchronized void redSchem(int schemId) { + Recorder.rByte(0xB1); + Recorder.rInt(schemId); + Recorder.flush(); + } + + public static synchronized void teamIds(int blueTeamId, int redTeamId) { + Recorder.rByte(0xB2); + Recorder.rInt(blueTeamId); + Recorder.rInt(redTeamId); + Recorder.flush(); + } + + public static synchronized void scoreboardTitle(String title){ + Recorder.rByte(0xC0); + Recorder.rString(title); + Recorder.flush(); + } + + public static synchronized void scoreboardData(String key, int value){ + Recorder.rByte(0xC1); + Recorder.rString(key); + Recorder.rInt(value); + Recorder.flush(); + } + + public static synchronized void tick(){ + Recorder.rByte(0xff); + Recorder.flush(); + } + + private static void checkWorldState(){ + tick(); + + if(FightSystem.getFightState() == FightState.SPECTATE) + return; + + for(TNTPrimed tnt : WORLD.getEntitiesByClass(TNTPrimed.class)){ + entityMoves(tnt); + entitySpeed(tnt); + } + } + + private static void spawnEntity(Entity e){ + Recorder.rInt(e.getEntityId()); + entityMoves(e); + entitySpeed(e); + } + + private static int blockToId(Block block){ + switch(Core.getVersion()){ + case 8: + case 9: + case 10: + case 12: + return RecordSystem_8.blockToId(block); + case 15: + default: + return RecordSystem_15.blockToId(block); + } + } +} diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/record/Recorder.java b/FightSystem_Main/src/de/steamwar/fightsystem/record/Recorder.java new file mode 100644 index 0000000..a332331 --- /dev/null +++ b/FightSystem_Main/src/de/steamwar/fightsystem/record/Recorder.java @@ -0,0 +1,90 @@ +/* + 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 . +*/ + +package de.steamwar.fightsystem.record; + +import java.util.ArrayList; +import java.util.List; + +public abstract class Recorder { + + private static final List recorders = new ArrayList<>(); + + public static void rBoolean(boolean b){ + recorders.forEach((recorder) -> recorder.writeBoolean(b)); + } + + public static void rByte(int b){ + recorders.forEach((recorder) -> recorder.writeByte(b)); + } + + public static void rShort(short s){ + recorders.forEach((recorder) -> recorder.writeShort(s)); + } + + public static void rInt(int i){ + recorders.forEach((recorder) -> recorder.writeInt(i)); + } + + public static void rLong(long l){ + recorders.forEach((recorder) -> recorder.writeLong(l)); + } + + public static void rFloat(float f){ + recorders.forEach((recorder) -> recorder.writeFloat(f)); + } + + public static void rDouble(double d){ + recorders.forEach((recorder) -> recorder.writeDouble(d)); + } + + public static void rString(String s){ + recorders.forEach((recorder) -> recorder.writeString(s)); + } + + public static void flush(){ + recorders.forEach(Recorder::doFlush); + } + + public static void closeAll(){ + while(!recorders.isEmpty()) + recorders.get(0).close(); + } + + protected Recorder(){ + recorders.add(this); + } + + protected void close(){ + closeRecorder(); + recorders.remove(this); + } + + protected abstract void writeBoolean(boolean b); + protected abstract void writeByte(int b); + protected abstract void writeShort(short s); + protected abstract void writeInt(int i); + protected abstract void writeLong(long l); + protected abstract void writeFloat(float f); + protected abstract void writeDouble(double d); + protected abstract void writeString(String s); + protected abstract void doFlush(); + + protected abstract void closeRecorder(); +} diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/record/SpectateConnection.java b/FightSystem_Main/src/de/steamwar/fightsystem/record/SpectateConnection.java new file mode 100644 index 0000000..9951321 --- /dev/null +++ b/FightSystem_Main/src/de/steamwar/fightsystem/record/SpectateConnection.java @@ -0,0 +1,147 @@ +/* + 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 . +*/ + +package de.steamwar.fightsystem.record; + +import de.steamwar.fightsystem.Config; +import org.bukkit.Bukkit; + +import java.io.*; +import java.net.Socket; +import java.util.logging.Level; + +public class SpectateConnection extends Recorder{ + + private Socket socket; + private DataOutputStream outputStream; + + SpectateConnection(){ + super(); + try { + this.socket = new Socket(Config.spectateIP, Config.spectatePort); + socket.setSoTimeout(1); // Wait a maximum of 1ms on a blocking operation (flush) + socket.setSoLinger(true, 1); // Wait a maximum of 1ms on close + socket.setTcpNoDelay(true); // Don't wait always on ack + this.outputStream = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); + } catch (IOException e) { + Bukkit.getLogger().log(Level.WARNING, "Could not init connection to spectate server", e); + close(); + } + } + + @Override + protected void writeBoolean(boolean b) { + try{ + outputStream.writeBoolean(b); + } catch (IOException e) { + close(); + Bukkit.getLogger().log(Level.SEVERE, "Could not send", e); + } + } + + @Override + protected void writeByte(int b) { + try{ + outputStream.writeByte(b); + } catch (IOException e) { + close(); + Bukkit.getLogger().log(Level.SEVERE, "Could not send", e); + } + } + + @Override + protected void writeShort(short s) { + try{ + outputStream.writeShort(s); + } catch (IOException e) { + close(); + Bukkit.getLogger().log(Level.SEVERE, "Could not send", e); + } + } + + @Override + protected void writeInt(int i) { + try{ + outputStream.writeInt(i); + } catch (IOException e) { + close(); + Bukkit.getLogger().log(Level.SEVERE, "Could not send", e); + } + } + + @Override + protected void writeLong(long l) { + try{ + outputStream.writeLong(l); + } catch (IOException e) { + close(); + Bukkit.getLogger().log(Level.SEVERE, "Could not send", e); + } + } + + @Override + protected void writeFloat(float f) { + try{ + outputStream.writeFloat(f); + } catch (IOException e) { + close(); + Bukkit.getLogger().log(Level.SEVERE, "Could not send", e); + } + } + + @Override + protected void writeDouble(double d) { + try{ + outputStream.writeDouble(d); + } catch (IOException e) { + close(); + Bukkit.getLogger().log(Level.SEVERE, "Could not send", e); + } + } + + @Override + protected void writeString(String s) { + try{ + outputStream.writeUTF(s); + } catch (IOException e) { + close(); + Bukkit.getLogger().log(Level.SEVERE, "Could not send", e); + } + } + + @Override + protected void doFlush() { + try{ + outputStream.flush(); + } catch (IOException e) { + close(); + Bukkit.getLogger().log(Level.SEVERE, "Could not flush", e); + } + } + + @Override + protected void closeRecorder() { + try { + socket.close(); + outputStream.close(); + } catch (IOException e) { + Bukkit.getLogger().log(Level.WARNING, "IOException on socket close", e); + } + } +} diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/utils/FightScoreboard.java b/FightSystem_Main/src/de/steamwar/fightsystem/utils/FightScoreboard.java index 3cf6766..7f628ae 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/utils/FightScoreboard.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/utils/FightScoreboard.java @@ -19,10 +19,12 @@ package de.steamwar.fightsystem.utils; +import de.steamwar.core.TPSWatcher; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightTeam; +import de.steamwar.fightsystem.record.RecordSystem; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.winconditions.*; import de.steamwar.scoreboard.SWScoreboard; @@ -91,6 +93,8 @@ public class FightScoreboard implements Listener { objective.addScore("§7Zeit: §a" + fightTime + "s", 3); } + setScore("§7TPS: §e" + TPSWatcher.getTPS(), 3); + if(fullScoreboard.contains(FightSystem.getFightState())){ if (Config.PercentSystem){ objective.addScore(Fight.getRedTeam().getPrefix() + "Schaden: " + (Math.round(100.0 * WinconditionPercentSystem.getRedPercent()) / 100.0) + "%", 1); @@ -112,6 +116,12 @@ public class FightScoreboard implements Listener { return objective; } + private static void setScore(String key, int value){ + objective.getScore(key).setScore(value); + if(Config.recording()) + RecordSystem.scoreboardData(key, value); + } + private static FightTeam getIndexDisplay() { if(index == 1) return Fight.redTeam; diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/utils/FightStatistics.java b/FightSystem_Main/src/de/steamwar/fightsystem/utils/FightStatistics.java index 0b948b3..23fcdf4 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/utils/FightStatistics.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/utils/FightStatistics.java @@ -47,6 +47,8 @@ public class FightStatistics { public static void saveStats(FightTeam winner, String windescription){ String gameMode = Config.SchematicType.toDB(); + if(!Fight.getBlueTeam().hasTeamLeader() || !Fight.getRedTeam().hasTeamLeader()) + return; SteamwarUser blueLeader = SteamwarUser.get(Fight.getBlueTeam().getLeader().getPlayer().getUniqueId()); SteamwarUser redLeader = SteamwarUser.get(Fight.getRedTeam().getLeader().getPlayer().getUniqueId()); int win = 0; diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/utils/WaterRemover.java b/FightSystem_Main/src/de/steamwar/fightsystem/utils/WaterRemover.java index 8506394..fcff47a 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/utils/WaterRemover.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/utils/WaterRemover.java @@ -49,14 +49,15 @@ public class WaterRemover { } private static void checkBlock(Block b, int startX, int startY, int startZ) throws IsAnOcean { - if(!isWater(b)) + if(!removeWater(b)) return; // If distance to original block is greater than 20 - if(Math.abs(startX - b.getX()) + Math.abs(startY - b.getY() + Math.abs(startZ - b.getZ())) >= 20) + if(Math.abs(startX - b.getX()) + Math.abs(startY - b.getY() + Math.abs(startZ - b.getZ())) >= 20){ + b.setType(Material.WATER); throw new IsAnOcean(); + } - b.setType(Material.AIR); try{ checkBlock(b.getRelative(BlockFace.EAST), startX, startY, startZ); checkBlock(b.getRelative(BlockFace.WEST), startX, startY, startZ); @@ -84,4 +85,19 @@ public class WaterRemover { return WaterRemover_14.isWater(block); } } + + public static boolean removeWater(Block block){ + //checks for water and removes it, if present + switch(Core.getVersion()){ + case 8: + case 9: + case 10: + case 12: + return WaterRemover_8.removeWater(block); + case 14: + case 15: + default: + return WaterRemover_14.removeWater(block); + } + } }