diff --git a/FightSystem_19/src/de/steamwar/fightsystem/utils/ProtocolWrapper19.java b/FightSystem_19/src/de/steamwar/fightsystem/utils/ProtocolWrapper19.java index 64a8692..2a99a89 100644 --- a/FightSystem_19/src/de/steamwar/fightsystem/utils/ProtocolWrapper19.java +++ b/FightSystem_19/src/de/steamwar/fightsystem/utils/ProtocolWrapper19.java @@ -43,13 +43,13 @@ public class ProtocolWrapper19 implements ProtocolWrapper { public void setSpawnPacketType(Object packet, EntityType type) { switch(type) { case PRIMED_TNT: - spawnType.set(packet, EntityTypes.as); + spawnType.set(packet, EntityTypes.av); break; case ARROW: - spawnType.set(packet, EntityTypes.d); + spawnType.set(packet, EntityTypes.e); break; case FIREBALL: - spawnType.set(packet, EntityTypes.S); + spawnType.set(packet, EntityTypes.V); break; } } diff --git a/FightSystem_8/src/de/steamwar/fightsystem/utils/BlockIdWrapper8.java b/FightSystem_8/src/de/steamwar/fightsystem/utils/BlockIdWrapper8.java index bb8bae2..06956c8 100644 --- a/FightSystem_8/src/de/steamwar/fightsystem/utils/BlockIdWrapper8.java +++ b/FightSystem_8/src/de/steamwar/fightsystem/utils/BlockIdWrapper8.java @@ -32,6 +32,9 @@ public class BlockIdWrapper8 implements BlockIdWrapper { @Override @SuppressWarnings("deprecation") public void setBlock(World world, int x, int y, int z, int blockState) { + if((blockState >> 4) > 256) // Illegal blockstate / corrupted replay + blockState = 0; + world.getBlockAt(x, y, z).setTypeIdAndData(blockState >> 4, (byte)(blockState & 0b1111), false); } diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java index fb9ee97..8d51340 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java @@ -90,6 +90,7 @@ public class FightSystem extends JavaPlugin { new ArrowPickup(); new BlockFadeListener(); new LeaveableArena(); + new ClickAnalyzer(); new HotbarKit.HotbarKitListener(); new OneShotStateDependent(ArenaMode.All, FightState.PreSchemSetup, () -> Fight.playSound(SWSound.BLOCK_NOTE_PLING.getSound(), 100.0f, 2.0f)); @@ -117,6 +118,7 @@ public class FightSystem extends JavaPlugin { new HellsBells(); new Meteor(); + new WinconditionAmongUs(); new NoPlayersOnlineCountdown(); new PreSchemCountdown(); @@ -161,6 +163,7 @@ public class FightSystem extends JavaPlugin { @Override public void onDisable() { GlobalRecorder.getInstance().close(); + ClickAnalyzer.close(); } public static void setSpectateState(FightTeam winFightTeam, String winreason, String subtitle, Object... params) { diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties index 126d650..ef060ac 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties +++ b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties @@ -238,3 +238,8 @@ WIN_LESS_DAMAGE={0} §7less damaged WIN_POINTS={0} has more points WIN_POINTS_EQUAL=§7Equal points WIN_TECHKO={0} §7is tech K.O. +WIN_IMPOSTER_DEAD={0} §7killed the imposter +WIN_CREWMATE_DEAD={0} §7killed all team mates + +AMONG_US_IMPOSTER_MESSAGE = §4You are the Imposter§8! §7Kill all your team mates to win the game! +AMONG_US_IMPOSTER_AMONG_MESSAGE = §4There is an Imposter among us§8! §7Kill him to win the game! diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties index 082f69f..2809513 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties +++ b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties @@ -223,3 +223,8 @@ WIN_LESS_DAMAGE={0} §7weniger beschädigt WIN_POINTS={0} hat mehr Punkte WIN_POINTS_EQUAL=§7Gleicher Punktestand WIN_TECHKO={0} §7ist Tech K.O. +WIN_IMPOSTER_DEAD={0} §7 hat den Imposter getötet +WIN_CREWMATE_DEAD={0} §7 hat alle Kameraden getötet + +AMONG_US_IMPOSTER_MESSAGE = §4Du bist ein Imposter§8! §7Du musst alle Kameraden töten, um zu gewinnen. +AMONG_US_IMPOSTER_AMONG_MESSAGE = §4Es ist ein Imposter unter uns§8! §7Tötet ihn, um das Spiel zu gewinnen! \ No newline at end of file diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java b/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java index 53486b5..47ba81f 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java @@ -32,6 +32,7 @@ import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.OneShotStateDependent; import de.steamwar.fightsystem.states.StateDependent; import de.steamwar.fightsystem.utils.*; +import de.steamwar.fightsystem.winconditions.Winconditions; import de.steamwar.inventory.SWItem; import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; @@ -128,7 +129,9 @@ public class FightTeam { WorldOfColorWrapper.impl.setTeamColor(team, color); BountifulWrapper.impl.setNametagVisibility(team); team.setNameTagVisibility(NameTagVisibility.HIDE_FOR_OTHER_TEAMS); - team.setAllowFriendlyFire(false); + if (!Config.ActiveWinconditions.contains(Winconditions.AMONG_US)) { + team.setAllowFriendlyFire(false); + } new OneShotStateDependent(ArenaMode.Restartable, FightState.PreLeaderSetup, () -> Bukkit.getScheduler().runTask(FightSystem.getPlugin(), this::reset)); new OneShotStateDependent(Config.replayserver(), FightState.PreLeaderSetup, () -> Bukkit.getScheduler().runTask(FightSystem.getPlugin(), this::reset)); diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/listener/ClickAnalyzer.java b/FightSystem_Core/src/de/steamwar/fightsystem/listener/ClickAnalyzer.java index dbc5b07..bf0ea32 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/listener/ClickAnalyzer.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/listener/ClickAnalyzer.java @@ -19,6 +19,7 @@ package de.steamwar.fightsystem.listener; +import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.utils.CraftbukkitWrapper; import org.bukkit.entity.Player; @@ -26,7 +27,6 @@ import org.bukkit.entity.Player; import java.io.*; public class ClickAnalyzer { - private ClickAnalyzer() {} private static final PrintStream output; @@ -38,7 +38,16 @@ public class ClickAnalyzer { } } - public static void onBlockPlace(Player player) { + public ClickAnalyzer() { + TinyProtocol.instance.addFilter(Recording.blockPlacePacket, this::onBlockPlace); + } + + public Object onBlockPlace(Player player, Object packet) { output.println(player.getName() + "," + System.nanoTime() + "," + CraftbukkitWrapper.impl.headRotation(player) + "," + player.getLocation().getPitch()); + return packet; + } + + public static void close() { + output.close(); } } diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/listener/InFightDamage.java b/FightSystem_Core/src/de/steamwar/fightsystem/listener/InFightDamage.java index 09ec33a..9be2167 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/listener/InFightDamage.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/listener/InFightDamage.java @@ -20,10 +20,12 @@ package de.steamwar.fightsystem.listener; import de.steamwar.fightsystem.ArenaMode; +import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.StateDependentListener; +import de.steamwar.fightsystem.winconditions.Winconditions; import net.md_5.bungee.api.ChatMessageType; import org.bukkit.entity.Arrow; import org.bukkit.entity.Player; @@ -36,7 +38,7 @@ import java.util.Objects; public class InFightDamage implements Listener { public InFightDamage() { - new StateDependentListener(ArenaMode.AntiReplay, FightState.Running, this); + new StateDependentListener(!Config.ActiveWinconditions.contains(Winconditions.AMONG_US), FightState.Running, this); } @EventHandler diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/listener/Recording.java b/FightSystem_Core/src/de/steamwar/fightsystem/listener/Recording.java index 202b4fd..ca3c654 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/listener/Recording.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/listener/Recording.java @@ -133,8 +133,6 @@ public class Recording implements Listener { public static final Class blockPlacePacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInBlockPlace"); private Object blockPlace(Player p, Object packet) { - ClickAnalyzer.onBlockPlace(p); - boolean mainHand = BountifulWrapper.impl.mainHand(packet); if(!isNotSent(p) && BountifulWrapper.impl.bowInHand(mainHand, p)) GlobalRecorder.getInstance().bowSpan(p, true, !mainHand); diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java b/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java index 007fb1a..7121594 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java @@ -46,6 +46,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.scheduler.BukkitTask; import java.io.EOFException; +import java.io.FilterInputStream; import java.io.IOException; import java.util.*; import java.util.logging.Level; @@ -100,12 +101,13 @@ public class PacketProcessor { packetDecoder[0x0b] = this::damage; packetDecoder[0x0c] = this::fireTick; packetDecoder[0x20] = this::arenaInfo; - packetDecoder[0x30] = this::block; + packetDecoder[0x30] = this::byteWorldHeightBlock; packetDecoder[0x31] = this::particle; packetDecoder[0x32] = this::sound; packetDecoder[0x33] = this::shortBlock; packetDecoder[0x34] = this::soundAtPlayer; packetDecoder[0x35] = this::shortRelativeBlock; + packetDecoder[0x36] = this::block; packetDecoder[0xa0] = () -> send(ChatMessageType.CHAT); packetDecoder[0xa1] = () -> send(ChatMessageType.ACTION_BAR); packetDecoder[0xa2] = () -> send(ChatMessageType.SYSTEM); @@ -218,7 +220,11 @@ public class PacketProcessor { float yaw = source.readFloat() + (rotateZ ? 180 : 0); byte headYaw = (byte)((source.readByte() + (rotateZ ? 128 : 0)) % 256); - execSync(() -> REntity.getEntity(entityId).move(locX, locY, locZ, pitch, yaw, headYaw)); + execSync(() -> { + REntity entity = REntity.getEntity(entityId); + if(entity != null) + entity.move(locX, locY, locZ, pitch, yaw, headYaw); + }); } private void entityDespawns() throws IOException { @@ -331,7 +337,7 @@ public class PacketProcessor { setBlock(x + Config.ArenaRegion.getMinX(), y + Config.BluePasteRegion.getMinY(), z + Config.ArenaRegion.getMinZ(), blockState); } - private void block() throws IOException { + private void byteWorldHeightBlock() throws IOException { int x = source.readInt() - arenaMinX; int y = Byte.toUnsignedInt(source.readByte()) - arenaMinY; int z = source.readInt() - arenaMinZ; @@ -345,6 +351,20 @@ public class PacketProcessor { setBlock(x + Config.ArenaRegion.getMinX(), y + Config.BluePasteRegion.getMinY(), z + Config.ArenaRegion.getMinZ(), blockState); } + private void block() throws IOException { + int x = source.readInt() - arenaMinX; + int y = source.readShort() - arenaMinY; + int z = source.readInt() - arenaMinZ; + int blockState = source.readInt(); + + if(rotateZ) { + x = Config.ArenaRegion.getSizeX() - x; + z = Config.ArenaRegion.getSizeZ() - z; + } + + setBlock(x + Config.ArenaRegion.getMinX(), y + Config.BluePasteRegion.getMinY(), z + Config.ArenaRegion.getMinZ(), blockState); + } + private void setBlock(int x, int y, int z, int blockState){ if(!Config.ArenaRegion.in2dRegion(x, z)) return; //Outside of the arena @@ -411,7 +431,12 @@ public class PacketProcessor { private void pasteEmbeddedSchem(FightTeam team) throws IOException { int schemId = source.readInt(); - Clipboard clipboard = SchematicData.clipboardFromStream(source, Core.getVersion() > 12); + Clipboard clipboard = SchematicData.clipboardFromStream(new FilterInputStream(source) { + @Override + public void close() { + // FAWE 1.12 calls close... + } + }, Core.getVersion() > 12); execSync(() -> team.pasteSchem(schemId, clipboard)); } diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/record/Recorder.java b/FightSystem_Core/src/de/steamwar/fightsystem/record/Recorder.java index fa50526..c028429 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/record/Recorder.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/record/Recorder.java @@ -100,12 +100,13 @@ public interface Recorder { * * ArenaInfo (0x20) + bool blueNegZ + byte arenaY + int arenaMinX + int arenaMinZ * - * BlockPacket (0x30) + pos int, byte, int + int BlockState + * DEPRECATED 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 * DEPRECATED ShortBlockPacket (0x33) + pos relative to ArenaMinX,ArenaMinZ byte, byte, byte + short BlockState * SoundAtPlayerPacket (0x34) + string (soundType, soundCategory) + float volume, pitch * ShortBlockPacket (0x35) + pos relative to ArenaMinX,BluePasteY,ArenaMinZ byte, byte, byte + short BlockState + * BlockPacket (0x36) + pos int, short, int + int BlockState * * * DEPRECATED ChatPacket (0xa0) + String message @@ -227,7 +228,7 @@ public interface Recorder { write(0x35, (byte)shortX, (byte)shortY, (byte)shortZ, (short)blockState); }else{ //Block packet - write(0x30, block.getX(), (byte)block.getY(), block.getZ(), blockState); + write(0x36, block.getX(), (short)block.getY(), block.getZ(), blockState); } } diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionAmongUs.java b/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionAmongUs.java new file mode 100644 index 0000000..0be9472 --- /dev/null +++ b/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionAmongUs.java @@ -0,0 +1,87 @@ +/* + * 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.winconditions; + +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.states.FightState; +import de.steamwar.fightsystem.states.OneShotStateDependent; +import de.steamwar.fightsystem.states.StateDependentListener; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.*; + +public class WinconditionAmongUs extends Wincondition implements Listener { + + private Map imposter = new HashMap<>(); + + private final Random random = new Random(); + + public WinconditionAmongUs() { + super("AmongUs"); + new OneShotStateDependent(Winconditions.AMONG_US, FightState.Ingame, () -> { + imposter.put(Fight.getRedTeam(), sendMessageAndReturnImposter(Fight.getRedTeam().getPlayers())); + imposter.put(Fight.getBlueTeam(), sendMessageAndReturnImposter(Fight.getBlueTeam().getPlayers())); + }); + new StateDependentListener(Winconditions.AMONG_US, FightState.Ingame, this); + } + + private FightPlayer sendMessageAndReturnImposter(Collection fightPlayers) { + List fightPlayerList = new ArrayList<>(fightPlayers); + FightPlayer imposter = fightPlayerList.get(random.nextInt(fightPlayerList.size())); + for (FightPlayer fightPlayer : fightPlayerList) { + if (fightPlayer == imposter) { + FightSystem.getMessage().send("AMONG_US_IMPOSTER_MESSAGE", fightPlayer.getPlayer()); + } else { + FightSystem.getMessage().send("AMONG_US_IMPOSTER_AMONG_MESSAGE", fightPlayer.getPlayer()); + } + } + return imposter; + } + + @EventHandler + public void handlePlayerDeath(PlayerDeathEvent event) { + handleDeath(event.getEntity().getPlayer()); + } + + @EventHandler + public void handlePlayerQuit(PlayerQuitEvent event) { + handleDeath(event.getPlayer()); + } + + private void handleDeath(Player player){ + FightTeam team = isTarget(player); + if(team == null) + return; + + FightPlayer current = team.getFightPlayer(player); + if (current == imposter.get(team)) { + win(team, "WIN_IMPOSTER_DEAD", team.getPrefix()); + } else if (team.getAlivePlayers() <= 2 && imposter.get(team).isLiving()) { + win(Fight.getOpposite(team), "WIN_CREWMATE_DEAD", Fight.getOpposite(team).getPrefix()); + } + } +} diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/Winconditions.java b/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/Winconditions.java index 9d7ae2a..620a247 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/Winconditions.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/Winconditions.java @@ -38,5 +38,6 @@ public enum Winconditions { PUMPKIN_TECH_KO, HELLS_BELLS, - METEOR + METEOR, + AMONG_US }