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
}