SteamWar/FightSystem
Archiviert
13
1

Commits vergleichen

..

18 Commits

Autor SHA1 Nachricht Datum
7b26b7bf91 Found Something
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2023-12-03 16:47:36 +01:00
Chaoscaot
ab08f5c131
Merge remote-tracking branch 'origin/AINavMesh' into chaos-ai
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
# Conflicts:
#	FightSystem_Core/src/de/steamwar/fightsystem/ai/AI.java
#	FightSystem_Core/src/de/steamwar/fightsystem/ai/LixfelAI.java
2023-09-05 20:56:03 +02:00
yoyosource
cffa60e43d Fix NavMesh
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-05 20:55:05 +02:00
yoyosource
578c0056cd Add TODO line
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-04 21:42:51 +02:00
yoyosource
f10238cae2 Update NavMesh and implement some kind of update
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-04 21:30:51 +02:00
yoyosource
69a0e02ab9 Update and Fix some NavMesh stuff
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-04 18:38:05 +02:00
yoyosource
45fd36907c Add some more TODOS
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-03 22:06:11 +02:00
yoyosource
c3e39296b5 Add Neighbour Navigation calculation
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-03 21:50:06 +02:00
yoyosource
2452d72f2c Add NavMesh
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-03 18:16:39 +02:00
39ccb113a8 Improved Pathplanning, WIP StateMachine
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Signed-off-by: Lixfel <agga-games@gmx.de>
2023-09-03 13:39:38 +02:00
Chaoscaot
71ddeb4ac8
Upgrades, Leude, Upgrades!
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-03 00:44:33 +02:00
Chaoscaot
c507e7ec97
Merge remote-tracking branch 'origin/lixfel-ai-v1' into chaos-ai 2023-09-02 23:19:43 +02:00
efb2537097 Improved Pathplanning (less suffocating)
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Signed-off-by: Lixfel <agga-games@gmx.de>
2023-09-02 23:19:07 +02:00
Chaoscaot
8e963bffef
Merge remote-tracking branch 'origin/lixfel-ai-v1' into chaos-ai 2023-09-02 22:18:36 +02:00
5a0614974e Fix planToAnywhere
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Signed-off-by: Lixfel <agga-games@gmx.de>
2023-09-02 22:18:13 +02:00
Chaoscaot
2151134dcc
Revert FightSystem
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-02 22:13:51 +02:00
Chaoscaot
fc7b8b6233
Basics™
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-09-02 22:12:18 +02:00
78ae119719 Fix Button press, Lixfel AI v1
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Signed-off-by: Lixfel <agga-games@gmx.de>
2023-09-02 21:51:05 +02:00
89 geänderte Dateien mit 2300 neuen und 2070 gelöschten Zeilen

Datei anzeigen

@ -39,7 +39,7 @@ public class CraftbukkitWrapper10 implements CraftbukkitWrapper {
System.arraycopy(backupChunk.getSections(), 0, chunk.getSections(), 0, chunk.getSections().length);
System.arraycopy(backupChunk.heightMap, 0, chunk.heightMap, 0, chunk.heightMap.length);
w.tileEntityListTick.removeAll(chunk.tileEntities.values());
if (!FightWorld.isPAPER()) {
if (!FightWorld.isPaper()) {
w.tileEntityList.removeAll(chunk.tileEntities.values());
}
chunk.tileEntities.clear();

Datei anzeigen

@ -39,7 +39,7 @@ public class CraftbukkitWrapper12 implements CraftbukkitWrapper {
System.arraycopy(backupChunk.getSections(), 0, chunk.getSections(), 0, chunk.getSections().length);
System.arraycopy(backupChunk.heightMap, 0, chunk.heightMap, 0, chunk.heightMap.length);
w.tileEntityListTick.removeAll(chunk.tileEntities.values());
if (!FightWorld.isPAPER()) {
if (!FightWorld.isPaper()) {
w.tileEntityList.removeAll(chunk.tileEntities.values());
}
chunk.tileEntities.clear();

Datei anzeigen

@ -46,8 +46,6 @@ dependencies {
implementation project(":FightSystem_9")
implementation project(":FightSystem_8")
compileOnly 'it.unimi.dsi:fastutil:8.5.6'
compileOnly swdep("Spigot-1.14")
compileOnly swdep("WorldEdit-1.15")
compileOnly swdep("SpigotCore")

Datei anzeigen

@ -21,31 +21,17 @@ package de.steamwar.fightsystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.core.Core;
import de.steamwar.fightsystem.Config;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import java.util.Map;
public class BlockIdWrapper14 implements BlockIdWrapper {
private static final Class<?> worldServer = Reflection.getClass("{nms.server.level}.WorldServer");
private static final Class<?> chunkProviderServer = Reflection.getClass("{nms.server.level}.ChunkProviderServer");
private static final Reflection.MethodInvoker getChunkProvider = Reflection.getTypedMethod(worldServer, null, chunkProviderServer);
private static final Class<?> playerChunkMap = Reflection.getClass("{nms.server.level}.PlayerChunkMap");
private static final Reflection.FieldAccessor<?> getPlayerChunkMap = Reflection.getField(chunkProviderServer, playerChunkMap, 0);
private static final Reflection.FieldAccessor<? extends Map> entityTrackers = Core.getVersion() > 15 ? Reflection.getField(playerChunkMap, Int2ObjectMap.class, 0) : Reflection.getField(playerChunkMap, org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.Int2ObjectMap.class, 0);
private static final Class<?> block = Reflection.getClass("{nms.world.level.block}.Block");
private static final Class<?> iBlockData = Reflection.getClass("{nms.world.level.block.state}.IBlockData");
private static final Class<?> blockPosition = Reflection.getClass("{nms.core}.BlockPosition");
private final Map trackers;
public BlockIdWrapper14() {
trackers = entityTrackers.get(getPlayerChunkMap.get(getChunkProvider.invoke(getWorldHandle.invoke(Config.world))));
}
private static final Reflection.MethodInvoker getCombinedId = Reflection.getTypedMethod(block, null, int.class, iBlockData);
private static final Reflection.MethodInvoker getNMS = Reflection.getTypedMethod(Reflection.getClass("{obc}.block.CraftBlock"), "getNMS", iBlockData);
@Override
@ -54,9 +40,11 @@ public class BlockIdWrapper14 implements BlockIdWrapper {
}
private static final Reflection.MethodInvoker getByCombinedId = Reflection.getTypedMethod(block, null, iBlockData, int.class);
private static final Reflection.MethodInvoker getWorldHandle = Reflection.getTypedMethod(Reflection.getClass("{obc}.CraftWorld"), "getHandle", worldServer);
private static final Reflection.ConstructorInvoker newBlockPosition = Reflection.getConstructor(blockPosition, int.class, int.class, int.class);
private static final Reflection.MethodInvoker getTypeAndData = Reflection.getMethod(worldServer, null, blockPosition, iBlockData, int.class);
private static final Reflection.MethodInvoker removeTileEntity = Reflection.getMethod(worldServer, Core.getVersion() > 15 ? "m" : "removeTileEntity", blockPosition);
private static final Reflection.MethodInvoker getChunkProvider = Reflection.getTypedMethod(worldServer, null, chunkProviderServer);
private static final Reflection.MethodInvoker flagDirty = Reflection.getMethod(chunkProviderServer, null, blockPosition);
@Override
public void setBlock(World world, int x, int y, int z, int blockState) {
@ -68,28 +56,4 @@ public class BlockIdWrapper14 implements BlockIdWrapper {
getTypeAndData.invoke(nworld, pos, blockData, 1042);
flagDirty.invoke(getChunkProvider.invoke(nworld), pos);
}
private static final Class<?> entityTracker = Reflection.getClass("{nms.server.level}.PlayerChunkMap$EntityTracker");
private static final Reflection.MethodInvoker updatePlayer = Reflection.getMethod(entityTracker, Core.getVersion() > 15 ? "b" : "updatePlayer", entityPlayer);
@Override
public void trackEntity(Player player, int entity) {
Object tracker = trackers.get(entity);
if(tracker != null)
updatePlayer.invoke(tracker, getPlayer.invoke(player));
}
private static final Reflection.MethodInvoker clearPlayer = Reflection.getMethod(entityTracker, Core.getVersion() > 15 ? "a" : "clear", entityPlayer);
@Override
public void untrackEntity(Player player, int entity) {
Object tracker = trackers.get(entity);
if(tracker != null)
clearPlayer.invoke(tracker, getPlayer.invoke(player));
}
private static final Reflection.MethodInvoker getMaterialByBlock = Reflection.getTypedMethod(Reflection.getClass("{obc}.util.CraftMagicNumbers"), "getMaterial", Material.class, block);
private static final Reflection.MethodInvoker getBlockByBlockData = Reflection.getTypedMethod(iBlockData, null, block);
@Override
public Material idToMaterial(int blockState) {
return (Material)getMaterialByBlock.invoke(null, getBlockByBlockData.invoke(getByCombinedId.invoke(null, blockState)));
}
}

Datei anzeigen

@ -38,7 +38,7 @@ public class CraftbukkitWrapper14 implements CraftbukkitWrapper {
System.arraycopy(backupChunk.getSections(), 0, chunk.getSections(), 0, chunk.getSections().length);
w.tileEntityListTick.removeAll(chunk.tileEntities.values());
if (!FightWorld.isPAPER()) {
if (!FightWorld.isPaper()) {
w.tileEntityList.removeAll(chunk.tileEntities.values());
}
chunk.tileEntities.clear();

Datei anzeigen

@ -108,9 +108,4 @@ public class FlatteningWrapper14 implements FlatteningWrapper {
public boolean isCrouching(Player player) {
return player.getPose() == Pose.SWIMMING;
}
@Override
public void sendBlockChange(Player player, Block block, Material type) {
player.sendBlockChange(block.getLocation(), type.createBlockData());
}
}

Datei anzeigen

@ -38,7 +38,7 @@ public class CraftbukkitWrapper15 implements CraftbukkitWrapper {
System.arraycopy(backupChunk.getSections(), 0, chunk.getSections(), 0, chunk.getSections().length);
w.tileEntityListTick.removeAll(chunk.tileEntities.values());
if (!FightWorld.isPAPER()) {
if (!FightWorld.isPaper()) {
w.tileEntityList.removeAll(chunk.tileEntities.values());
}
chunk.tileEntities.clear();

Datei anzeigen

@ -48,7 +48,6 @@ dependencies {
compileOnly 'com.mojang:datafixerupper:4.0.26'
compileOnly 'io.netty:netty-all:4.1.68.Final'
compileOnly 'com.mojang:authlib:1.5.25'
compileOnly 'it.unimi.dsi:fastutil:8.5.6'
compileOnly swdep("Spigot-1.18")
compileOnly swdep("WorldEdit-1.15")

Datei anzeigen

@ -1,82 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.fightsystem.Config;
import it.unimi.dsi.fastutil.shorts.Short2ObjectArrayMap;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.SectionPosition;
import net.minecraft.network.protocol.game.PacketPlayOutBlockChange;
import net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange;
import net.minecraft.world.level.block.state.IBlockData;
import org.bukkit.block.data.BlockData;
import java.util.ArrayList;
import java.util.List;
public class HullHiderWrapper18 implements HullHiderWrapper {
private static final Reflection.MethodInvoker getState = Reflection.getTypedMethod(Reflection.getClass("{obc}.block.data.CraftBlockData"), "getState", IBlockData.class);
@Override
public Object generateBlockChangePacket(List<Hull.IntVector> changes) {
List<Object> blockdata = new ArrayList<>(changes.size());
changes.removeIf(change -> {
BlockData data = Config.world.getBlockData(change.getX(), change.getY(), change.getZ());
boolean unchanged = data.getMaterial() == Config.ObfuscateWith || Config.HiddenBlocks.contains(data.getMaterial());
if(!unchanged)
blockdata.add(getState.invoke(data));
return unchanged;
});
if(changes.isEmpty())
return null;
return generateBlockChangePacket(changes, blockdata.toArray());
}
private Object generateBlockChangePacket(List<Hull.IntVector> changes, Object[] blockdata) {
if(changes.size() > 1) {
Hull.IntVector section = changes.get(0);
section = new Hull.IntVector(section.getX() >> 4, section.getY() >> 4, section.getZ() >> 4);
int xOffset = 16*section.getX();
int yOffset = 16*section.getY();
int zOffset = 16*section.getZ();
short[] pos = new short[changes.size()];
for(int i = 0; i < changes.size(); i++) {
Hull.IntVector change = changes.get(i);
pos[i] = (short) (((change.getX()-xOffset) << 8) + ((change.getZ()-zOffset) << 4) + (change.getY()-yOffset));
}
return constructMultiBlockChange(section, pos, blockdata);
} else {
Hull.IntVector pos = changes.get(0);
return new PacketPlayOutBlockChange(new BlockPosition(pos.getX(), pos.getY(), pos.getZ()), (IBlockData) blockdata[0]);
}
}
protected Object constructMultiBlockChange(Hull.IntVector section, short[] pos, Object[] blockdata) {
return new PacketPlayOutMultiBlockChange(SectionPosition.a(section.getX(), section.getY(), section.getZ()), new Short2ObjectArrayMap<>(pos, blockdata, blockdata.length), false);
}
}

Datei anzeigen

@ -46,7 +46,6 @@ dependencies {
implementation project(":FightSystem_18")
compileOnly 'org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT'
compileOnly 'it.unimi.dsi:fastutil:8.5.6'
compileOnly swdep("Spigot-1.20")
}

Datei anzeigen

@ -1,32 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.utils;
import it.unimi.dsi.fastutil.shorts.Short2ObjectArrayMap;
import net.minecraft.core.SectionPosition;
import net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange;
public class HullHiderWrapper20 extends HullHiderWrapper18 {
@Override
protected Object constructMultiBlockChange(Hull.IntVector section, short[] pos, Object[] blockdata) {
return new PacketPlayOutMultiBlockChange(SectionPosition.a(section.getX(), section.getY(), section.getZ()), new Short2ObjectArrayMap<>(pos, blockdata, blockdata.length));
}
}

Datei anzeigen

@ -19,25 +19,10 @@
package de.steamwar.fightsystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.fightsystem.Config;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
public class BlockIdWrapper8 implements BlockIdWrapper {
private static final Class<?> entityTracker = Reflection.getClass("{nms}.EntityTracker");
private static final Reflection.FieldAccessor<?> getEntityTracker = Reflection.getField(worldServer, entityTracker, 0);
private static final Class<?> intHashMap = Reflection.getClass("{nms}.IntHashMap");
private static final Reflection.FieldAccessor<?> getTrackedEntities = Reflection.getField(entityTracker, intHashMap, 0);
private final Object trackers;
public BlockIdWrapper8() {
trackers = getTrackedEntities.get(getEntityTracker.get(getWorldHandle.invoke(Config.world)));
}
@Override
@SuppressWarnings("deprecation")
public int blockToId(Block block) {
@ -52,31 +37,4 @@ public class BlockIdWrapper8 implements BlockIdWrapper {
world.getBlockAt(x, y, z).setTypeIdAndData(blockState >> 4, (byte)(blockState & 0b1111), false);
}
private static final Class<?> entityTrackerEntry = Reflection.getClass("{nms}.EntityTrackerEntry");
private static final Reflection.MethodInvoker get = Reflection.getTypedMethod(intHashMap, "get", Object.class, int.class);
private static final Reflection.MethodInvoker updatePlayer = Reflection.getMethod(entityTrackerEntry, "updatePlayer", entityPlayer);
@Override
public void trackEntity(Player player, int entity) {
Object tracker = get.invoke(trackers, entity);
if(tracker != null)
updatePlayer.invoke(tracker, getPlayer.invoke(player));
}
private static final Reflection.MethodInvoker clearPlayer = Reflection.getMethod(entityTrackerEntry, "a", entityPlayer);
@Override
public void untrackEntity(Player player, int entity) {
Object tracker = get.invoke(trackers, entity);
if(tracker != null)
clearPlayer.invoke(tracker, getPlayer.invoke(player));
}
@Override
@SuppressWarnings("deprecation")
public Material idToMaterial(int blockState) {
if((blockState >> 4) > 256) // Illegal blockstate / corrupted replay
blockState = 0;
return Material.getMaterial(blockState >> 4);
}
}

Datei anzeigen

@ -83,10 +83,4 @@ public class FlatteningWrapper8 implements FlatteningWrapper {
public boolean isCrouching(Player player) {
return false;
}
@Override
@SuppressWarnings("deprecation")
public void sendBlockChange(Player player, Block block, Material type) {
player.sendBlockChange(block.getLocation(), type, (byte)0);
}
}

Datei anzeigen

@ -1,55 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.fightsystem.Config;
import org.bukkit.Material;
import java.util.List;
public class HullHiderWrapper8 implements HullHiderWrapper {
private static final Reflection.ConstructorInvoker newMultiBlockChange = Reflection.getConstructor("{nms}.PacketPlayOutMultiBlockChange", int.class, short[].class, Reflection.getClass("{nms}.Chunk"));
private static final Reflection.MethodInvoker getHandle = Reflection.getMethod("{obc}.CraftChunk", "getHandle");
@Override
public Object generateBlockChangePacket(List<Hull.IntVector> changes) {
changes.removeIf(change -> {
Material material = Config.world.getBlockAt(change.getX(), change.getY(), change.getZ()).getType();
return material == Config.ObfuscateWith || Config.HiddenBlocks.contains(material);
});
if(changes.isEmpty())
return null;
Hull.IntVector chunk = changes.get(0);
chunk = new Hull.IntVector(chunk.getX() >> 4, chunk.getY() >> 4, chunk.getZ() >> 4);
int xOffset = 16*chunk.getX();
int zOffset = 16*chunk.getZ();
short[] pos = new short[changes.size()];
for(int i = 0; i < changes.size(); i++) {
Hull.IntVector change = changes.get(i);
pos[i] = (short) (((change.getX()-xOffset) << 12) + ((change.getZ()-zOffset) << 8) + change.getY());
}
return newMultiBlockChange.invoke(pos.length, pos, getHandle.invoke(Config.world.getChunkAt(chunk.getX(), chunk.getZ())));
}
}

Datei anzeigen

@ -39,7 +39,7 @@ public class CraftbukkitWrapper9 implements CraftbukkitWrapper {
System.arraycopy(backupChunk.getSections(), 0, chunk.getSections(), 0, chunk.getSections().length);
System.arraycopy(backupChunk.heightMap, 0, chunk.heightMap, 0, chunk.heightMap.length);
w.tileEntityListTick.removeAll(chunk.tileEntities.values());
if (!FightWorld.isPAPER()) {
if (!FightWorld.isPaper()) {
w.tileEntityList.removeAll(chunk.tileEntities.values());
}
chunk.tileEntities.clear();

Datei anzeigen

@ -47,9 +47,6 @@ dependencies {
compileOnly 'io.netty:netty-all:4.1.68.Final'
compileOnly 'com.mojang:authlib:1.5.25'
compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'
compileOnly swdep("WorldEdit-1.15")
compileOnly swdep("SpigotCore")
}

Datei anzeigen

@ -61,14 +61,10 @@ Schematic:
z: 0
# The schematic type that can be chosen in this arena
Type: Normal # defaults to Normal if missing
# The schematic types that are also allowed to be chosen in this arena
SubTypes: [] # defaults to empty List
# Shortcut of the schematic type
Shortcut: "" # defaults to "" if missing
# Spigot (1.8) material for GUIs
Material: STONE_BUTTON # defaults to STONE_BUTTON if missing
# Manual check of schematic necessary
ManualCheck: true # defaults to true if missing
# If the schematics should be rotated during pasting
Rotate: true # defaults to true if missing
# If the schematics should be pasted aligned to the borders instead of centered
@ -114,6 +110,8 @@ WinConditions: # defaults to none if missing
# - CAPTAIN_DEAD
# - PERCENT_SYSTEM
# - WHITELIST_PERCENT
# - RELATIVE_PERCENT
# - POINTS
# - POINTS_AIRSHIP
@ -123,18 +121,12 @@ WinConditions: # defaults to none if missing
# - HELLS_BELLS
# - METEOR
# - PERSISTENT_DAMAGE
# - TNT_DISTRIBUTION
WinConditionParams:
# The time of any of the timeout win conditions in seconds
TimeoutTime: 1200 # defaults to 1200 if missing
# The percentage when any of the percent win conditions limits or triggers a win
PercentWin: 7.0 # defaults to 7.0 if missing
# Does the percentage still change after the start of the enter phase
PercentEntern: true # defaults to true if missing
# Is Blocks a whitelist (true) or blacklist (false)
BlocksWhitelist: false # defaults to false if missing
# Special Blocks (Valid spigot material values) used by the percent win conditions
Blocks: [] # defaults to none if missing

Datei anzeigen

@ -21,7 +21,10 @@ package de.steamwar.fightsystem;
import de.steamwar.fightsystem.utils.Region;
import de.steamwar.fightsystem.winconditions.Winconditions;
import de.steamwar.sql.*;
import de.steamwar.sql.Event;
import de.steamwar.sql.EventFight;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@ -80,7 +83,6 @@ public class Config {
public static final boolean OnlyPublicSchematics;
public static final boolean IgnorePublicOnly;
public static final de.steamwar.sql.SchematicType SchematicType;
public static final List<de.steamwar.sql.SchematicType> SubTypes;
public static final boolean RedRotate;
public static final boolean BlueRotate;
public static final boolean PasteAligned;
@ -104,8 +106,6 @@ public class Config {
//win condition parameters
public static final int TimeoutTime;
public static final double PercentWin;
public static final boolean PercentEntern;
public static final boolean PercentBlocksWhitelist;
public static final Set<Material> PercentBlocks;
//default kits
@ -117,13 +117,13 @@ public class Config {
//tech hider parameter
public static final boolean TechhiderActive;
public static final Set<Material> HiddenBlocks;
public static final Set<String> HiddenBlocks;
public static final Set<String> HiddenBlockEntities;
public static final Material ObfuscateWith;
public static final String ObfuscateWith;
//event parameter
private static final int EventKampfID;
public static final EventFight EventKampf;
private static final Set<Integer> Referees;
public static final int EventTeamBlueID;
public static final int EventTeamRedID;
public static final boolean BothTeamsPublic;
@ -138,14 +138,10 @@ public class Config {
//replay system parameter
public static final String spectateIP = "127.0.0.1";
public static final int SpectatePort;
public static final int spectatePort = 2222;
public static final int ReplayID;
static{
CheckSchemID = Integer.parseInt(System.getProperty("checkSchemID", "0"));
PrepareSchemID = Integer.parseInt(System.getProperty("prepareSchemID", "0"));
ReplayID = Integer.parseInt(System.getProperty("replay", "0"));
String configFile = System.getProperty("config", "config.yml");
if(!new File(FightSystem.getPlugin().getDataFolder(), configFile).exists()) {
FightSystem.getPlugin().saveDefaultConfig();
@ -185,7 +181,6 @@ public class Config {
int schemsizeZ = config.getInt("Schematic.Size.z");
RanksEnabled = !config.getStringList("Ranks").isEmpty();
SchematicType = de.steamwar.sql.SchematicType.fromDB(Objects.requireNonNull(config.getString("Schematic.Type", "normal")));
SubTypes = config.getStringList("Schematic.SubTypes").stream().map(de.steamwar.sql.SchematicType::fromDB).collect(Collectors.toList());
IgnorePublicOnly = config.getBoolean("Schematic.IgnorePublicOnly", false);
boolean rotate = config.getBoolean("Schematic.Rotate", true);
PasteAligned = config.getBoolean("Schematic.PasteAligned", false);
@ -200,8 +195,6 @@ public class Config {
TimeoutTime = config.getInt("WinConditionParams.TimeoutTime", 1200);
PercentWin = config.getDouble("WinConditionParams.PercentWin", 7.0);
PercentEntern = config.getBoolean("WinConditionParams.PercentEntern", true);
PercentBlocksWhitelist = config.getBoolean("WinConditionParams.BlocksWhitelist", false);
PercentBlocks = Collections.unmodifiableSet(config.getStringList("WinConditionParams.Blocks").stream().map(Material::valueOf).collect(Collectors.toSet()));
EnterStages = Collections.unmodifiableList(config.getIntegerList("EnterStages"));
@ -214,8 +207,8 @@ public class Config {
ForbiddenItems = Collections.unmodifiableSet(config.getStringList("Kits.ForbiddenItems").stream().map(Material::valueOf).collect(Collectors.toSet()));
TechhiderActive = config.getBoolean("Techhider.Active", false);
ObfuscateWith = Material.getMaterial(config.getString("Techhider.ObfuscateWith", "end_stone").toUpperCase());
HiddenBlocks = config.getStringList("Techhider.HiddenBlocks").stream().map(String::toUpperCase).map(Material::getMaterial).collect(Collectors.toSet());
ObfuscateWith = config.getString("Techhider.ObfuscateWith", "end_stone").toUpperCase();
HiddenBlocks = Collections.unmodifiableSet(new HashSet<>(config.getStringList("Techhider.HiddenBlocks")));
HiddenBlockEntities = Collections.unmodifiableSet(new HashSet<>(config.getStringList("Techhider.HiddenBlockEntities")));
if(schemsizeX < 0){
@ -310,25 +303,25 @@ public class Config {
RedRotate = teamRedRotate;
BlueRotate = teamBlueRotate;
RedPasteRegion = Region.fromSize(teamRedCornerX, teamRedCornerY, teamRedCornerZ, schemsizeX, schemsizeY, schemsizeZ);
BluePasteRegion = Region.fromSize(blueCornerX, blueCornerY, blueCornerZ, schemsizeX, schemsizeY, schemsizeZ);
RedPasteRegion = new Region(teamRedCornerX, teamRedCornerY, teamRedCornerZ, schemsizeX, schemsizeY, schemsizeZ);
BluePasteRegion = new Region(blueCornerX, blueCornerY, blueCornerZ, schemsizeX, schemsizeY, schemsizeZ);
RedExtendRegion = Region.withExtension(teamRedCornerX, teamRedCornerY, teamRedCornerZ, schemsizeX, schemsizeY, schemsizeZ, PreperationArea, PreperationArea, PreperationArea);
BlueExtendRegion = Region.withExtension(blueCornerX, blueCornerY, blueCornerZ, schemsizeX, schemsizeY, schemsizeZ, PreperationArea, PreperationArea, PreperationArea);
ArenaRegion = Region.withExtension(arenaMinX, blueCornerY, arenaMinZ, arenaMaxX - arenaMinX, schemsizeY, arenaMaxZ - arenaMinZ, 0, PreperationArea, 0);
PlayerRegion = new Region(arenaMinX, underBorder, arenaMinZ, arenaMaxX, world.getMaxHeight(), arenaMaxZ);
RedExtendRegion = new Region(teamRedCornerX, teamRedCornerY, teamRedCornerZ, schemsizeX, schemsizeY, schemsizeZ, PreperationArea, PreperationArea, PreperationArea);
BlueExtendRegion = new Region(blueCornerX, blueCornerY, blueCornerZ, schemsizeX, schemsizeY, schemsizeZ, PreperationArea, PreperationArea, PreperationArea);
ArenaRegion = new Region(arenaMinX, blueCornerY, arenaMinZ, arenaMaxX - arenaMinX, schemsizeY, arenaMaxZ - arenaMinZ, 0, PreperationArea, 0);
PlayerRegion = new Region(arenaMinX, underBorder, arenaMinZ, arenaMaxX - arenaMinX, world.getMaxHeight() - underBorder, arenaMaxZ - arenaMinZ);
int eventKampfID = Integer.parseInt(System.getProperty("fightID", "0"));
if(eventKampfID >= 1){
EventKampf = EventFight.get(eventKampfID);
if(EventKampf == null){
EventKampfID = Integer.parseInt(System.getProperty("fightID", "0"));
if(EventKampfID >= 1){
EventFight eventFight = EventFight.get(EventKampfID);
if(eventFight == null){
Bukkit.getLogger().log(Level.SEVERE, "Failed to load EventFight");
Bukkit.shutdown();
}
assert EventKampf != null;
Team team1 = Team.get(EventKampf.getTeamBlue());
Team team2 = Team.get(EventKampf.getTeamRed());
assert eventFight != null;
Team team1 = Team.get(eventFight.getTeamBlue());
Team team2 = Team.get(eventFight.getTeamRed());
if(team1 == null || team2 == null){
Bukkit.getLogger().log(Level.SEVERE, "Failed to load Team");
@ -344,11 +337,9 @@ public class Config {
EventTeamBlueID = team1.getTeamId();
EventTeamRedID = team2.getTeamId();
BothTeamsPublic = EventTeamRedID == 0 && EventTeamBlueID == 0;
SpectatePort = EventKampf.getSpectatePort();
LiveReplay = SpectatePort != 0;
Referees = Referee.get(Config.EventKampf.getEventID());
EventKampf = eventFight;
Event event = Event.get(EventKampf.getEventID());
Event event = Event.get(eventFight.getEventID());
if(BothTeamsPublic) {
OnlyPublicSchematics = true;
MaximumTeamMembers = Integer.MAX_VALUE;
@ -356,6 +347,7 @@ public class Config {
OnlyPublicSchematics = event.publicSchemsOnly();
MaximumTeamMembers = event.getMaximumTeamMembers();
}
LiveReplay = event.spectateSystem();
}else{
//No event
TeamRedColor = config.getString("Red.Prefix", "§c");
@ -367,10 +359,8 @@ public class Config {
EventTeamRedID = 0;
EventKampf = null;
BothTeamsPublic = true;
Referees = Collections.emptySet();
MaximumTeamMembers = Integer.MAX_VALUE;
LiveReplay = false;
SpectatePort = -ReplayID;
}
String blueLeader = System.getProperty("blueLeader", null);
@ -384,13 +374,17 @@ public class Config {
else
RedLeader = null;
CheckSchemID = Integer.parseInt(System.getProperty("checkSchemID", "0"));
PrepareSchemID = Integer.parseInt(System.getProperty("prepareSchemID", "0"));
ReplayID = Integer.parseInt(System.getProperty("replay", "0"));
if(CheckSchemID != 0){
mode = ArenaMode.CHECK;
}else if(PrepareSchemID != 0){
mode = ArenaMode.PREPARE;
}else if(eventKampfID >= 1){
}else if(EventKampfID >= 1){
mode = ArenaMode.EVENT;
}else if(eventKampfID == -1){
}else if(EventKampfID == -1){
mode = ArenaMode.TEST;
}else if(ReplayID != 0){
mode = ArenaMode.REPLAY;
@ -403,13 +397,15 @@ public class Config {
return ArenaMode.Test.contains(mode);
}
public static boolean replayserver(){
return ReplayID < 0;
return ReplayID == -1;
}
public static boolean blueNegZ(){
return BlueToRedZ > 0;
}
public static boolean isReferee(Player player) {
return Referees.contains(SteamwarUser.get(player.getUniqueId()).getId());
if(EventKampf == null)
return false;
return SteamwarUser.get(player.getUniqueId()).getId() == EventKampf.getKampfleiter();
}
}

Datei anzeigen

@ -21,12 +21,13 @@ package de.steamwar.fightsystem;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.core.Core;
import de.steamwar.fightsystem.ai.LixfelAI;
import de.steamwar.fightsystem.ai.navmesh.NavMesh;
import de.steamwar.fightsystem.ai.chaos.ChaosAI;
import de.steamwar.fightsystem.commands.*;
import de.steamwar.fightsystem.countdown.*;
import de.steamwar.fightsystem.event.HellsBells;
import de.steamwar.fightsystem.event.Meteor;
import de.steamwar.fightsystem.event.PersistentDamage;
import de.steamwar.fightsystem.event.TNTDistributor;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.fight.FightWorld;
@ -39,25 +40,22 @@ import de.steamwar.fightsystem.record.GlobalRecorder;
import de.steamwar.fightsystem.record.LiveRecorder;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.OneShotStateDependent;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.fightsystem.utils.*;
import de.steamwar.fightsystem.winconditions.*;
import de.steamwar.message.Message;
import de.steamwar.sql.SchematicNode;
import lombok.Getter;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
public class FightSystem extends JavaPlugin {
@Getter
private static FightSystem plugin;
private Message message;
private FightTeam lastWinner;
private String lastWinreason;
private TechHiderWrapper techHider;
private HullHider hullHider;
@Override
public void onLoad() {
@ -84,6 +82,7 @@ public class FightSystem extends JavaPlugin {
});
new Chat();
new ArenaBorder();
new TeamArea();
new IngameDeath();
new InFightDamage();
new InFightInventory();
@ -100,7 +99,7 @@ public class FightSystem extends JavaPlugin {
new RunningWorldInteraction();
new PersonalKitCreator();
new ArrowStopper();
new StateDependentListener(ArenaMode.All, FightState.All, BountifulWrapper.impl.newDenyArrowPickupListener());
new ArrowPickup();
new BlockFadeListener();
new LeaveableArena();
new ClickAnalyzer();
@ -111,7 +110,6 @@ public class FightSystem extends JavaPlugin {
new EnterHandler();
techHider = new TechHiderWrapper();
hullHider = new HullHider();
new FightWorld();
new FightUI();
new FightStatistics();
@ -121,7 +119,9 @@ public class FightSystem extends JavaPlugin {
new WinconditionCaptainDead();
new WinconditionBlocks(Winconditions.WATER_TECH_KO, "WaterTechKO", "BAR_WATER", FlatteningWrapper.impl::isWater);
new WinconditionBlocks(Winconditions.PUMPKIN_TECH_KO, "PumpkinTechKO", "BAR_CANNONS", block -> block.getType() == WinconditionBlocks.PUMPKIN_LANTERN);
new WinconditionPercent(Winconditions.PERCENT_SYSTEM, "Percent");
new WinconditionPercentSystem();
new WinconditionBlacklistPercent();
new WinconditionWhitelistPercent();
new WinconditionPoints();
new WinconditionPointsAirShip();
new WinconditionTimeout();
@ -132,8 +132,6 @@ public class FightSystem extends JavaPlugin {
new HellsBells();
new Meteor();
new PersistentDamage();
new TNTDistributor();
new WinconditionAmongUs();
new NoPlayersOnlineCountdown();
@ -157,7 +155,6 @@ public class FightSystem extends JavaPlugin {
new LockschemCommand();
new StateCommand();
new SkipCommand();
new TPSWarpCommand();
new UnrankCommand();
new WinCommand();
@ -169,18 +166,17 @@ public class FightSystem extends JavaPlugin {
if(Config.mode == ArenaMode.EVENT) {
FightState.setFightState(FightState.PRE_SCHEM_SETUP);
}else if(Config.mode == ArenaMode.CHECK){
SchematicNode checkSchematicNode = SchematicNode.getSchematicNode(Config.CheckSchemID);
Fight.getBlueTeam().setSchem(checkSchematicNode);
if (checkSchematicNode.getName().endsWith("-prepared")) {
SchematicNode unpreparedSchematicNode = SchematicNode.getSchematicNode(checkSchematicNode.getOwner(), checkSchematicNode.getName().substring(0, checkSchematicNode.getName().length() - 9), checkSchematicNode.getParent());
if (unpreparedSchematicNode != null) {
Fight.getRedTeam().setSchem(unpreparedSchematicNode);
}
}
Fight.getBlueTeam().setSchem(SchematicNode.getSchematicNode(Config.CheckSchemID));
}else if(Config.mode == ArenaMode.PREPARE) {
Fight.getUnrotated().setSchem(SchematicNode.getSchematicNode(Config.PrepareSchemID));
}
FightStatistics.unrank();
Bukkit.getScheduler().runTask(getPlugin(), () -> {
new ChaosAI(Fight.getBlueTeam());
new LixfelAI(Fight.getRedTeam(), SteamwarUser.get(-1));
});
}
@Override
@ -197,6 +193,15 @@ public class FightSystem extends JavaPlugin {
FightState.setFightState(FightState.SPECTATE);
}
public static FightSystem getPlugin() {
return plugin;
}
public static void broadcast(String msg, Object... params) {
getMessage().broadcast(msg, params);
GlobalRecorder.getInstance().system(msg, params);
}
public static Message getMessage() {
return plugin.message;
}
@ -213,10 +218,6 @@ public class FightSystem extends JavaPlugin {
return plugin.techHider;
}
public static HullHider getHullHider() {
return plugin.hullHider;
}
public static void shutdown() {
//Staggered kick to prevent lobby overloading
if(Bukkit.getOnlinePlayers().isEmpty()){

Datei anzeigen

@ -51,9 +51,6 @@ INFO_RANKED=§7Ranked§8: §e{0}
INFO_LEADER=§7Leader {0}§8: {1}
INFO_SCHEMATIC=§7Schematic {0}§8: §e{1} §7from {2}, Rank: {3}
TPSWARP_HELP=§8/§7tpswarp §8[§eticks per second§8]
TPSWARP_SET=§7TPS set to §e{0}
# GUI
STATE_TITLE=Fight state
@ -78,7 +75,6 @@ KITSEARCH_TITLE=Search for kit
SCHEM_NO_ENEMY=§cNo schematic selection without an opponent
SCHEM_TITLE={0} selection
SCHEM_PUBLIC=§ePublic {0}
SCHEM_UNCHECKED=§eUnchecked {0}
SCHEM_PRIVATE=§ePrivate {0}
SCHEM_NO_PRIVATE=§7No private {0} present
SCHEM_PRIVATE_FORBIDDEN=§7No private {0} allowed
@ -103,7 +99,6 @@ SPECTATE_COUNTDOWN=until the arena is reset
# Fight
SCHEMATIC_UNLOADABLE=§cUnable to load schematic
SCHEMATIC_CHOSEN=§7{0} §e{1} §7chosen
SCHEMATIC_UNCHECKED=§7Team {0} §7has chosen an §eunchecked §7schematic§8!
TEAM_READY=§aTeam ready
TEAM_NOT_READY=§c§mTeam ready
SKIP_READY=§aSkipping to next event

Datei anzeigen

@ -45,9 +45,6 @@ REMOVE_HELP=§8/§eremove §8[§eSpieler§8]
NOT_FIGHTLEADER=§cDu bist nicht Kampfleiter
WIN_HELP=§8/§7win §8[§eTeam §8oder §etie§8]
TPSWARP_HELP=§8/§7tpswarp §8[§eTicks pro Sekunde§8]
TPSWARP_SET=§7TPS auf §e{0} §7gesetzt
# GUI
STATE_TITLE=Kampfstatus
@ -72,7 +69,6 @@ KITSEARCH_TITLE=Nach Kit suchen
SCHEM_NO_ENEMY=§cKeine Schematicwahl ohne Gegner
SCHEM_TITLE={0}-Auswahl
SCHEM_PUBLIC=§eÖffentliches {0}
SCHEM_UNCHECKED=§eUngeprüftes {0}
SCHEM_PRIVATE=§ePrivates {0}
SCHEM_NO_PRIVATE=§7Kein privates {0} vorhanden
SCHEM_PRIVATE_FORBIDDEN=§7Kein privates {0} erlaubt
@ -97,7 +93,6 @@ SPECTATE_COUNTDOWN=bis die Arena zurückgesetzt wird
# Fight
SCHEMATIC_UNLOADABLE=§cSchematic konnte nicht geladen werden
SCHEMATIC_CHOSEN=§7{0} §e{1} §7gewählt
SCHEMATIC_UNCHECKED=§7Team {0} §7hat eine §eungeprüfte §7Schematic gewählt§8!
TEAM_READY=§aTeam bereit
TEAM_NOT_READY=§c§mTeam bereit
SKIP_READY=§aBeschleunigung zum nächsten Event

Datei anzeigen

@ -35,13 +35,13 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Note;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Lectern;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Openable;
import org.bukkit.block.data.Powerable;
import org.bukkit.block.data.*;
import org.bukkit.block.data.type.Comparator;
import org.bukkit.block.data.type.NoteBlock;
import org.bukkit.block.data.type.Repeater;
import org.bukkit.block.data.type.Switch;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@ -68,7 +68,7 @@ public abstract class AI {
return ais.get(uuid);
}
private final FightTeam team;
protected final FightTeam team;
private final LivingEntity entity;
private final BukkitTask task;
private final Queue<Action> queue = new ArrayDeque<>();
@ -120,6 +120,22 @@ public abstract class AI {
Chat.broadcastChat("PARTICIPANT_CHAT", team.getColoredName(), entity.getName(), message);
}
protected Vector toAIPosition(Vector location) {
Region extend = team.getExtendRegion();
if(Fight.getUnrotated() == team)
return new Vector(
location.getX() - extend.getMinX(),
location.getY() - team.getSchemRegion().getMinY(),
location.getZ() - extend.getMinZ()
);
else
return new Vector(
extend.getMaxX() - location.getX(),
location.getY() - team.getSchemRegion().getMinY(),
extend.getMaxZ() - location.getZ()
);
}
protected Vector getPosition() {
Location location = entity.getLocation();
Region extend = team.getExtendRegion();
@ -155,8 +171,10 @@ public abstract class AI {
return;
Location location = translate(pos, true);
if(interactionDistanceViolation(location))
if(interactionDistanceViolation(location)) {
chat("2 smoll pepe hönds!");
return;
}
Block block = location.getBlock();
if(block.getType() == Material.AIR)
@ -170,8 +188,10 @@ public abstract class AI {
@Override
public void run() {
Location location = translate(pos, true);
if(interactionDistanceViolation(location))
if(interactionDistanceViolation(location)) {
chat("Ich komme da nicht dran!");
return;
}
interact(location.getBlock());
}
@ -205,15 +225,17 @@ public abstract class AI {
public void run() {
Location location = entity.getLocation();
Location target = translate(pos, false);
/*
if(Math.abs(location.getX() - target.getX()) > 1 || Math.abs(location.getY() - target.getY()) > 1.2 || Math.abs(location.getZ() - target.getZ()) > 1) {
FightSystem.getPlugin().getLogger().log(Level.INFO, () -> entity.getName() + ": Overdistance movement " + location.toVector() + " " + target.toVector());
return;
}
*/
if(!team.getFightPlayer(entity).canEntern() && !team.getExtendRegion().inRegion(target))
return;
entity.teleport(target, PlayerTeleportEvent.TeleportCause.COMMAND);
entity.teleport(target, PlayerTeleportEvent.TeleportCause.PLUGIN);
}
});
}
@ -249,12 +271,34 @@ public abstract class AI {
powerable.setPowered(false);
block.setBlockData(powerable);
updateButton(block);
}, type.name().endsWith("STONE_BUTTON") ? 20 : 30);
}
powerable.setPowered(!isPowered);
}
block.setBlockData(data);
if(data instanceof Switch) {
updateButton(block);
}
}
private void updateButton(Block block) {
Switch sw = (Switch) block.getBlockData();
FaceAttachable.AttachedFace face = sw.getAttachedFace();
if (face == FaceAttachable.AttachedFace.FLOOR) {
update(block.getRelative(BlockFace.DOWN));
} else if (face == FaceAttachable.AttachedFace.CEILING) {
update(block.getRelative(BlockFace.UP));
} else {
update(block.getRelative(sw.getFacing().getOppositeFace()));
}
}
private void update(Block block) {
BlockData data = block.getBlockData();
block.setType(Material.BARRIER);
block.setBlockData(data);
}
private void run() {
@ -265,7 +309,7 @@ public abstract class AI {
queue.poll().run();
}
private Location translate(Vector pos, boolean blockPos) {
public Location translate(Vector pos, boolean blockPos) {
Region extend = team.getExtendRegion();
if(Fight.getUnrotated() == team)
return new Location(

Datei anzeigen

@ -19,42 +19,102 @@
package de.steamwar.fightsystem.ai;
import de.steamwar.entity.REntityServer;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.ai.navmesh.NavMesh;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.List;
import java.util.Random;
import java.util.*;
public class LixfelAI extends AI {
private final Random random = new Random();
private LixfelPathplanner pathplanner;
private final REntityServer entityServer = new REntityServer();
private final FightTeam team;
private final NavMesh navMesh;
public LixfelAI(FightTeam team, String user) {
super(team, SteamwarUser.get(user));
public LixfelAI(FightTeam team, SteamwarUser user) {
super(team, user);
this.team = team;
navMesh = new NavMesh(team, entityServer);
}
@Override
public SchematicNode chooseSchematic() {
List<SchematicNode> publics = SchematicNode.getAllSchematicsOfType(0, Config.SchematicType.toDB());
SchematicNode schem = publics.get(new Random().nextInt(publics.size()));
pathplanner = new LixfelPathplanner(schem);
return schem;
if (false) {
List<SchematicNode> publics = SchematicNode.getAllSchematicsOfType(0, Config.SchematicType.toDB());
SchematicNode schem = publics.get(new Random().nextInt(publics.size()));
return schem;
}
// return SchematicNode.byIdAndUser(SteamwarUser.get(0), 111476);
return SchematicNode.byIdAndUser(SteamwarUser.get(0), 98711);
}
@Override
public boolean acceptJoinRequest(Player player, FightTeam team) {
if (team == this.team) {
entityServer.addPlayer(player);
}
return super.acceptJoinRequest(player, team);
}
private Vector source = null;
private Vector destination = null;
private int index = 0;
@Override
protected void plan() {
setReady();
Vector destination = pathplanner.getWalkable().get(random.nextInt(pathplanner.getWalkable().size()));
List<Vector> path = pathplanner.plan(getPosition(), destination);
if(!path.isEmpty())
chat("Path size: " + path.size());
for(Vector p : path) {
move(p);
if (navMesh == null) return;
if (!getEntity().isOnGround() && getEntity().getLocation().getBlock().getType() != Material.LADDER) return;
if (source == null || destination == null) {
source = getEntity().getLocation().toVector();
List<Vector> walkableBlocks = navMesh.getWalkableBlocks(source);
if (walkableBlocks.isEmpty()) return;
destination = walkableBlocks.get(random.nextInt(walkableBlocks.size()));
index = 0;
}
List<Vector> oldRoute = navMesh.path(source, destination);
navMesh.update(getEntity().getLocation().toVector());
List<Vector> path = navMesh.path(source, destination);
// TODO: New Route detection
if (path.isEmpty()) {
source = null;
destination = null;
chat("no route");
return;
}
if (!oldRoute.equals(path)) {
source = getEntity().getLocation().toVector();
index = 0;
chat("new route");
return;
}
if (index == 0) {
chat(source + " -> " + destination + " = " + path.size());
}
if (index > path.size()) {
source = null;
destination = null;
chat("route cancelled");
return;
}
Vector location = path.get(index++);
move(toAIPosition(location));
if (index == path.size()) {
source = null;
destination = null;
}
}
}

Datei anzeigen

@ -19,30 +19,60 @@
package de.steamwar.fightsystem.ai;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BaseBlock;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.utils.WorldeditWrapper;
import de.steamwar.sql.SchematicData;
import de.steamwar.sql.SchematicNode;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.*;
import org.bukkit.util.Vector;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
public class LixfelPathplanner {
private static BlockType getBlockType(Clipboard clipboard, BlockVector3 vector) {
return clipboard.getBlock(vector).getBlockType();
private static double blockHeight(Clipboard clipboard, BlockVector3 vector) {
BaseBlock block = clipboard.getFullBlock(vector);
if(block.getBlockType().getMaterial().isFullCube())
return 1.0;
BlockData data = BukkitAdapter.adapt(block);
Material material = data.getMaterial();
if(material.isSolid()) {
if(material.isInteractable()) {
if(data instanceof Stairs)
return 1.0;
else if(data instanceof Fence)
return 1.5;
else if(data instanceof Bed)
return 0.5625;
} else {
if(data instanceof Slab)
return ((Slab)data).getType() == Slab.Type.BOTTOM ? 0.5 : 1.0;
else if(data instanceof Wall)
return 1.5;
else if(data instanceof GlassPane || material == Material.IRON_BARS)
return 1.0;
}
} else {
if(material == Material.LADDER || material == Material.SCAFFOLDING)
return -1.0;
else if(material.name().endsWith("_CARPET"))
return 0.0625;
}
return 0.0;
}
private static boolean nonsolid(Clipboard clipboard, BlockVector3 vector) {
return !getBlockType(clipboard, vector).getMaterial().isSolid();
}
private static Vector toBukkit(BlockVector3 vector) {
return new Vector(vector.getX() + 0.5, vector.getY(), vector.getZ() + 0.5);
private static Vector toBukkit(BlockVector3 vector, double height) {
return new Vector(vector.getX() + 0.5, vector.getY() + height, vector.getZ() + 0.5);
}
private final List<Vector> walkable = new ArrayList<>();
@ -61,25 +91,33 @@ public class LixfelPathplanner {
}
private void fillWalkable(Clipboard clipboard) {
BlockVector3 min = clipboard.getRegion().getMinimumPoint().subtract(Config.PreperationArea, 0, Config.PreperationArea); //TODO assumes nonextended Schematic with maximal size
Vector clipboardToSchem = new Vector(Config.BluePasteRegion.getSizeX(), Config.BluePasteRegion.getSizeY(), Config.BluePasteRegion.getSizeZ())
.subtract(WorldeditWrapper.impl.getDimensions(clipboard))
.multiply(0.5)
.add(new Vector(Config.PreperationArea, 0, Config.PreperationArea));
BlockVector3 diff = clipboard.getRegion().getMinimumPoint().subtract(clipboardToSchem.getBlockX(), clipboardToSchem.getBlockY(), clipboardToSchem.getBlockZ());
Region region = clipboard.getRegion();
clipboard.getRegion().forEach(vector -> {
BlockVector3 below = vector.subtract(0, 1, 0);
if(!region.contains(below))
BlockVector3 above = vector.add(0, 1, 0);
double aboveHeight = region.contains(above) ? blockHeight(clipboard, above) : 0.0;
if(aboveHeight > 0.0)
return;
BlockType belowMaterial = getBlockType(clipboard, below);
BlockVector3 above = vector.add(0, 1, 0);
if(nonsolid(clipboard, vector)) {
if(
(belowMaterial.getMaterial().isSolid() || belowMaterial.getId().equals("minecraft:ladder")) &&
(!region.contains(above) || nonsolid(clipboard, above))
)
walkable.add(toBukkit(vector.subtract(min)));
} else {
if(!region.contains(above))
walkable.add(toBukkit(above.subtract(min)));
}
double belowHeight = region.contains(below) ? blockHeight(clipboard, below) : 0.0;
double height = blockHeight(clipboard, vector);
if(height == 0.0 && Math.abs(belowHeight) < 1.0)
return;
if(height >= 1.0 && region.contains(above))
return;
if(height < 0.0)
height = 0.0;
walkable.add(toBukkit(vector.subtract(diff), height));
});
for(Vector vector : walkable) {
@ -87,24 +125,42 @@ public class LixfelPathplanner {
}
}
@Deprecated
public Vector walkableNearby(double eyeHeight, double distance, List<Vector> nearby) {
List<Vector> moddedNearby = nearby.stream().map(n -> n.clone().subtract(new Vector(0, eyeHeight, 0))).collect(Collectors.toList());
return walkable.stream()
.filter(vector -> moddedNearby.stream()
.allMatch(n -> n.distance(vector) <= distance && !neighbouring(n, vector)))
.findAny().orElse(null);
}
public List<Vector> planToAnywhere(Vector start, Vector destination) {
Vector intermediate = walkable.stream().filter(vector -> neighbouring(vector, destination)).findAny().orElse(null);
if(intermediate == null)
return Collections.emptyList();
List<Vector> plan = plan(start, intermediate);
List<Vector> plan = new ArrayList<>(plan(start, intermediate));
plan.add(destination);
return plan;
}
public List<Vector> planToRange(Vector start, Vector destination, double range) {
return plan(start, walkable.stream().filter(vector -> vector.distance(destination) <= range).collect(Collectors.toList()));
}
public List<Vector> plan(Vector start, Vector destination) {
if(neighbouring(start, destination))
return Collections.singletonList(destination);
return plan(start, Collections.singletonList(destination));
}
public List<Vector> plan(Vector start, List<Vector> destinations) {
for(Vector destination : destinations)
if(neighbouring(start, destination))
return Collections.singletonList(destination);
Map<Vector, Vector> approach = new HashMap<>();
Set<Vector> checking = Collections.singleton(destination);
Set<Vector> checking = new HashSet<>(destinations);
while(!checking.isEmpty()) {
Set<Vector> toCheck = new HashSet<>();
@ -122,7 +178,7 @@ public class LixfelPathplanner {
List<Vector> path = new ArrayList<>();
path.add(firstStep);
while(path.get(path.size()-1) != destination) {
while(!destinations.contains(path.get(path.size()-1))) {
path.add(approach.get(path.get(path.size()-1)));
}

Datei anzeigen

@ -17,23 +17,42 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.event;
package de.steamwar.fightsystem.ai.chaos;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentTask;
import de.steamwar.fightsystem.winconditions.Winconditions;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
public class TNTDistributor {
public class Cannon {
public final Vector[] tnt;
public final Vector button;
public final Vector load;
public final Vector escape;
public final String name;
public TNTDistributor() {
new StateDependentTask(Winconditions.TNT_DISTRIBUTION, FightState.Running, () -> Fight.teams().forEach(team -> team.getPlayers().forEach(fp -> {
if(!fp.isLiving())
return;
public Cannon(String name, Vector[] tnt, Vector button, Vector load, Vector escape) {
this.tnt = tnt;
this.button = button;
this.load = load;
this.escape = escape;
this.name = name;
}
fp.ifPlayer(player -> player.getInventory().addItem(new ItemStack(Material.TNT, 20)));
})), 300, 300);
public Vector[] getTnt() {
return tnt;
}
public Vector getButton() {
return button;
}
public Vector getLoad() {
return load;
}
public Vector getEscape() {
return escape;
}
public String getName() {
return name;
}
}

Datei anzeigen

@ -0,0 +1,267 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.ai.chaos;
import de.steamwar.entity.REntityServer;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.ai.AI;
import de.steamwar.fightsystem.ai.chaos.gears.Gear;
import de.steamwar.fightsystem.ai.chaos.gears.TheUnderground;
import de.steamwar.fightsystem.ai.navmesh.NavMesh;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.util.Vector;
import java.util.*;
public class ChaosAI extends AI {
private State state = State.PRE_PREPARE;
private static final Gear gear = TheUnderground.THE_UNDERGROUND;
private Cannon currentCannon;
private boolean igniteMg = false;
private static final Random random = new Random();
public static Map<FightTeam, Boolean> onePrepares = new HashMap<>();
private boolean prepares = false;
private static final Map<FightTeam, Set<Cannon>> cannonsShot = new HashMap<>();
private final NavMesh navMesh;
private final REntityServer entityServer = new REntityServer();
private Vector source = null;
private Vector destination = null;
private int index = 0;
private State nextState = null;
public ChaosAI(FightTeam team) {
this(team, SteamwarUser.get(14533));
}
public ChaosAI(FightTeam team, SteamwarUser user) {
super(team, user);
this.navMesh = new NavMesh(team, entityServer);
if (Boolean.FALSE.equals(onePrepares.getOrDefault(team, false))) {
prepares = true;
onePrepares.put(team, true);
}
}
@Override
public SchematicNode chooseSchematic() {
return SchematicNode.getSchematicNode(gear.getSchematicId());
}
@Override
protected void plan() {
switch (state) {
case PRE_PREPARE:
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> {
state = State.PREPARE;
}, 20 * 15);
state = State.WAIT;
break;
case PREPARE:
prepare();
break;
case PREPARE_READY:
if (prepares) {
for (Vector prepareButton : gear.getPrepareButtons()) {
interact(prepareButton);
}
}
setReady();
state = State.WAIT_TILL_START;
break;
case WAIT_TILL_START:
if (FightState.ingame()) {
state = State.IGNITE_MG;
startFight();
}
break;
case IGNITE_MG:
if(igniteMg) {
if (prepares) {
interact(gear.getMgButton());
chat("Die MG ist angezündet!");
}
state = State.WAIT;
currentCannon = randomCannon();
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> state = State.FIGHT, 20 * 9);
}
break;
case FIGHT:
fireCannon(currentCannon);
break;
case LOAD_CANNON:
loadCannon(currentCannon);
break;
case ESCAPE:
cannonsShot.computeIfAbsent(team, fightTeam -> new HashSet<>()).remove(currentCannon);
currentCannon = randomCannon();
state = State.WAIT;
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> state = State.FIGHT, 20 * 4);
break;
case WAIT:
break;
case WALK:
if (!getEntity().isOnGround() && getEntity().getLocation().getBlock().getType() != Material.LADDER) return;
List<Vector> oldRoute = navMesh.path(source, destination);
navMesh.update(getEntity().getLocation().toVector());
List<Vector> path = navMesh.path(source, destination);
if (path.isEmpty()) {
source = null;
destination = null;
state = nextState;
chat("no route");
return;
}
if (!oldRoute.equals(path)) {
source = getEntity().getLocation().toVector();
index = 0;
chat("new route");
return;
}
if (index == 0) {
chat(source + " -> " + destination + " = " + path.size());
}
Vector loc = path.get(index++);
move(toAIPosition(loc));
if (index == path.size()) {
source = null;
destination = null;
state = nextState;
}
break;
}
}
private void moveTo(Vector vec, State nextState) {
source = getEntity().getLocation().toVector();
Vector currentBest = null;
for (Vector vector : navMesh.getWalkableBlocks(source)) {
if (currentBest == null || vector.distanceSquared(vec) < currentBest.distanceSquared(vec)) {
currentBest = vector;
}
}
destination = currentBest;
index = 0;
state = State.WALK;
this.nextState = nextState;
}
@Override
public void stop() {
chat("gege wp eZ win 4nus");
if (currentCannon != null) {
cannonsShot.computeIfAbsent(team, fightTeam -> new HashSet<>()).remove(currentCannon);
}
super.stop();
}
@Override
public boolean acceptJoinRequest(Player player, FightTeam team) {
if (team == this.team) {
entityServer.addPlayer(player);
}
return team == this.team;
}
public void fireCannon(Cannon cannon) {
chat("Ich feuere " + cannon.name + " an!");
moveTo(cannon.load.clone().add(new Vector(0.5, 0, 0.5)), State.LOAD_CANNON);
}
private void loadCannon(Cannon cannon) {
if (cannon.button == null) {
for (int i = 0; i < 20; i++) {
for (Vector vector : cannon.tnt) {
setTNT(vector);
}
for (int j = 0; j < 30; j++) {
getBlock(gear.getMgButton());
}
}
} else {
for (Vector vector : cannon.tnt) {
setTNT(vector);
}
interact(cannon.button);
}
if (currentCannon.escape != null) {
moveTo(cannon.getEscape().clone().add(new Vector(0.5, 0, 0.5)), State.ESCAPE);
}
}
private Cannon randomCannon() {
Cannon nextCannon = gear.getCannons()[random.nextInt(gear.getCannons().length)];
while (cannonsShot.computeIfAbsent(team, fightTeam -> new HashSet<>()).contains(nextCannon)) {
nextCannon = gear.getCannons()[random.nextInt(gear.getCannons().length)];
}
cannonsShot.computeIfAbsent(team, fightTeam -> new HashSet<>()).add(nextCannon);
return nextCannon;
}
public void startFight() {
chat("gl&hf");
if (prepares) {
chat("Ich zünde die MG an!");
}
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> {
igniteMg = true;
}, 20L * gear.getMgTime());
}
public void prepare() {
chat("Prepare your fkin 4nus");
if (prepares) {
moveTo(gear.getBridge().clone().add(new Vector(0.5, 0, 0.5)), State.PREPARE_READY);
}
}
private enum State {
PRE_PREPARE,
PREPARE,
PREPARE_READY,
WAIT_TILL_START,
IGNITE_MG,
FIGHT,
LOAD_CANNON,
ESCAPE,
WAIT,
WALK,
}
}

Datei anzeigen

@ -0,0 +1,66 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.ai.chaos.gears;
import de.steamwar.fightsystem.ai.chaos.Cannon;
import org.bukkit.util.Vector;
public class Gear {
private final Cannon[] cannons;
private final Vector bridge;
private final Vector[] prepareButtons;
private final Vector mgButton;
private final int mgTime;
private final int schematicId;
protected Gear(Cannon[] cannons, Vector bridge, Vector[] prepareButtons, Vector mgButton, int mgTime, int schematicId) {
this.cannons = cannons;
this.bridge = bridge;
this.prepareButtons = prepareButtons;
this.mgButton = mgButton;
this.mgTime = mgTime;
this.schematicId = schematicId;
}
public Cannon[] getCannons() {
return cannons;
}
public Vector getBridge() {
return bridge;
}
public Vector[] getPrepareButtons() {
return prepareButtons;
}
public Vector getMgButton() {
return mgButton;
}
public int getMgTime() {
return mgTime;
}
public int getSchematicId() {
return schematicId;
}
}

Datei anzeigen

@ -0,0 +1,184 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.ai.chaos.gears;
import de.steamwar.fightsystem.ai.chaos.Cannon;
import org.bukkit.util.Vector;
public class TheUnderground {
public static final Vector[] DS_LEFT_TNT = new Vector[] {
new Vector(40, 24, 12),
new Vector(39, 24, 12),
new Vector(38, 23, 12),
new Vector(38, 24, 12),
new Vector(40, 23, 15),
new Vector(40, 23, 14),
new Vector(40, 24, 15),
new Vector(40, 24, 14),
new Vector(38, 23, 15),
new Vector(38, 23, 14),
new Vector(38, 24, 15),
new Vector(38, 24, 14),
new Vector(40, 23, 12),
};
public static final Vector DS_LEFT_BUTTON = new Vector(39, 25, 11);
public static final Vector DS_LEFT_LOAD = new Vector(39, 25, 13);
public static final Vector DS_LEFT_ESCAPE = new Vector(31, 26, 13);
public static final Cannon DS_LEFT = new Cannon("Downstäb Links", DS_LEFT_TNT, DS_LEFT_BUTTON, DS_LEFT_LOAD, DS_LEFT_ESCAPE);
public static final Vector[] DS_RIGHT_TNT = new Vector[] {
new Vector(12, 24, 12),
new Vector(11, 24, 12),
new Vector(10, 23, 12),
new Vector(10, 24, 12),
new Vector(10, 23, 15),
new Vector(10, 23, 14),
new Vector(10, 24, 15),
new Vector(10, 24, 14),
new Vector(12, 23, 14),
new Vector(12, 24, 14),
new Vector(12, 23, 15),
new Vector(12, 24, 15),
new Vector(12, 23, 12),
};
public static final Vector DS_RIGHT_BUTTON = new Vector(11, 25, 11);
public static final Vector DS_RIGHT_LOAD = new Vector(11, 25, 13);
public static final Vector DS_RIGHT_ESCAPE = new Vector(19, 26, 13);
public static final Cannon DS_RIGHT = new Cannon("Downstäb Rechts", DS_RIGHT_TNT, DS_RIGHT_BUTTON, DS_RIGHT_LOAD, DS_RIGHT_ESCAPE);
public static final Vector[] STATIC_LEFT_TNT = new Vector[] {
new Vector(37, 17, 15),
new Vector(37, 17, 14),
new Vector(37, 18, 16),
new Vector(37, 18, 15),
new Vector(37, 18, 14),
new Vector(36, 17, 16),
new Vector(36, 17, 15),
new Vector(36, 17, 14),
new Vector(36, 18, 16),
new Vector(36, 18, 15),
new Vector(36, 18, 14),
new Vector(37, 17, 16),
};
public static final Vector STATIC_LEFT_BUTTON = new Vector(38, 18, 11);
public static final Vector STATIC_LEFT_LOAD = new Vector(37, 17, 12);
public static final Vector STATIC_LEFT_ESCAPE = new Vector(30, 13, 9);
public static final Cannon STATIC_LEFT = new Cannon("Lupf Links", STATIC_LEFT_TNT, STATIC_LEFT_BUTTON, STATIC_LEFT_LOAD, STATIC_LEFT_ESCAPE);
public static final Vector[] STATIC_RIGHT_TNT = new Vector[] {
new Vector(14, 17, 15),
new Vector(14, 18, 16),
new Vector(14, 18, 15),
new Vector(14, 17, 14),
new Vector(14, 18, 14),
new Vector(13, 17, 16),
new Vector(13, 17, 15),
new Vector(13, 17, 14),
new Vector(13, 18, 16),
new Vector(13, 18, 15),
new Vector(13, 18, 14),
new Vector(14, 17, 16),
};
public static final Vector STATIC_RIGHT_BUTTON = new Vector(12, 18, 11);
public static final Vector STATIC_RIGHT_LOAD = new Vector(13, 17, 12);
public static final Vector STATIC_RIGHT_ESCAPE = new Vector(20, 13, 9);
public static final Cannon STATIC_RIGHT = new Cannon("Lupf Rechts", STATIC_RIGHT_TNT, STATIC_RIGHT_BUTTON, STATIC_RIGHT_LOAD, STATIC_RIGHT_ESCAPE);
public static final Vector[] AK_TNT = new Vector[] {
new Vector(10, 7, 17),
new Vector(10, 11, 17),
new Vector(10, 10, 17),
new Vector(10, 8, 17),
new Vector(10, 9, 17),
new Vector(10, 7, 15),
new Vector(11, 7, 15),
new Vector(12, 7, 15),
new Vector(10, 10, 15),
new Vector(11, 10, 15),
new Vector(12, 10, 15),
new Vector(12, 8, 15),
new Vector(12, 9, 15),
new Vector(11, 8, 15),
new Vector(11, 9, 15),
new Vector(10, 8, 15),
new Vector(10, 9, 15),
new Vector(10, 7, 19),
new Vector(11, 7, 19),
new Vector(12, 7, 19),
new Vector(12, 8, 19),
new Vector(11, 8, 19),
new Vector(10, 8, 19),
new Vector(10, 10, 19),
new Vector(11, 10, 19),
new Vector(12, 10, 19),
new Vector(12, 9, 19),
new Vector(11, 9, 19),
new Vector(10, 9, 19),
new Vector(10, 6, 17),
};
public static final Vector AK_BUTTON = new Vector(9, 9, 16);
public static final Vector AK_LOAD = new Vector(11, 8, 17);
public static final Cannon AK = new Cannon("Arschkratzer", AK_TNT, AK_BUTTON, AK_LOAD, null);
public static final Vector[] HA_RIGHT_TNT = new Vector[] {
new Vector(23, 5, 9),
new Vector(23, 6, 9),
new Vector(23, 7, 9),
new Vector(23, 8, 9),
};
public static final Vector[] HA_LEFT_TNT = new Vector[] {
new Vector(27, 5, 9),
new Vector(27, 6, 9),
new Vector(27, 7, 9),
new Vector(27, 8, 9),
};
public static final Vector HA_RIGHT_LOAD = new Vector(23, 8, 8);
public static final Vector HA_LEFT_LOAD = new Vector(27, 8, 8);
public static final Cannon HA_LEFT = new Cannon("Halbautomatik Links", HA_LEFT_TNT, null, HA_LEFT_LOAD, null);
public static final Cannon HA_RIGHT = new Cannon("Halbautomatik Rechts", HA_RIGHT_TNT, null, HA_RIGHT_LOAD, null);
public static final Vector BRIDGE_POS = new Vector(25, 14, 24);
public static final Vector BRIDGE_SHIELDS = new Vector(25, 15, 25);
public static final Vector BRIDGE_MG = new Vector(21, 15, 24);
public static final Gear THE_UNDERGROUND = new Gear(
new Cannon[] {
DS_LEFT,
DS_RIGHT,
STATIC_LEFT,
STATIC_RIGHT,
AK,
HA_LEFT,
HA_RIGHT,
//Cannon.AK,
},
BRIDGE_POS,
new Vector[] {
BRIDGE_SHIELDS
},
BRIDGE_MG,
21,
124667
);
}

Datei anzeigen

@ -0,0 +1,25 @@
event(events.PlaceBlock, function(e)
if storage.player.get("recording") then
pos = {math.floor(e.x), math.floor(e.y) - 100, math.floor(e.z)}
storage.player.get("recordingPos")[storage.player.get("recordingCount")] = pos
storage.player.set("recordingCount", storage.player.get("recordingCount") + 1)
end
end)
command("recorder", function(args)
if storage.player.get("recording") then
storage.player.set("recording", false)
storage.player.set("recordingCount", 0)
print("private static final Vector[] positions = new Vector[] {")
for k, v in pairs(storage.player.get("recordingPos")) do
print("new Vector(" .. v[1] .. ", " .. v[2] .. ", " .. v[3] .. "),")
end
print("};")
print("Stopped recording")
else
storage.player.set("recording", true)
storage.player.set("recordingCount", 0)
storage.player.set("recordingPos", {})
print("Started recording")
end
end)

Datei anzeigen

@ -0,0 +1,343 @@
-- This file is a part of the SteamWar software.
--
-- Copyright (C) 2021 SteamWar.de-Serverteam
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Affero General Public License for more details.
--
-- You should have received a copy of the GNU Affero General Public License
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
---
--- This file contains the definitions for the SteamWar.de script API.
--- It is used by the IDE to provide code completion and type checking.
--- Created by Chaoscaot
---
inventory = {}
---@param title string
---@param size number
---@return Inventory
function inventory.create(title, size) return nil end
---@alias InventoryClick 'LEFT' | 'SHIFT_LEFT' | 'RIGHT' | 'SHIFT_RIGHT' | 'MIDDLE' | 'NUMBER_KEY'
---@class Inventory
local Inventory = {}
---@overload fun(slot: number, material: string, name: string, handler: fun(click: InventoryClick)): void
---@overload fun(slot: number, material: string, name: string, handler: fun(click: InventoryClick), lore: string[]): void
---@overload fun(slot: number, material: string, name: string, handler: fun(click: InventoryClick), lore: string[], enchanted: boolean): void
---@param slot number
---@param material string
---@param name string
---@param handler fun(click: InventoryClick): void
---@param lore string[]
---@param enchanted boolean
---@param amount number
---@return void
function Inventory.item(slot, material, name, handler, lore, enchanted, amount) end
---@param handler fun(): void
---@return void
function Inventory.setCloseHandler(handler) end
---@return void
function Inventory.open() end
player = {}
---@return string
---Get the name of the player.
function player.name() return "" end
---@return void
function player.chat(...) end
---@return void
---Send a message to the actionbar of the player.
function player.actionbar(...) end
---@overload fun(): number
---@param newX number
function player.x(newX) end
---@overload fun(): number
---@param newY number
function player.y(newY) end
---@overload fun(): number
---@param newZ number
function player.z(newZ) end
---@overload fun(): number
---@param newYaw number
function player.yaw(newYaw) end
---@overload fun(): number
---@param newPitch number
function player.pitch(newPitch) end
---@return boolean
function player.sneaking() return nil end
---@return boolean
function player.sprinting() return nil end
---@overload fun(): number
---@param newSlot number
function player.slot(newSlot) end
---@return string
function player.item() return nil end
---@return string
function player.offHandItem() return nil end
---@return void
function player.closeInventory() end
---@field nextBool fun(): boolean
random = {}
---@overload fun(): number
---@overload fun(bound: number): number
---@param origin number
---@param bound number
---@return number
function random.nextInt(origin, bound) return nil end
---@overload fun(): number
---@overload fun(bound: number): number
---@param origin number
---@param bound number
---@return number
function random.nextDouble(origin, bound) return nil end
---@return boolean
function random.nextBool() return nil end
---@alias RegionType 'wg' | 'mwg' | 'as' | 'ws' | 'ws_inner' | 'ws_rumpf' | 'ws_rahmen' | 'spawn'
---@class iregion
---@field tnt tnt
---@field trace trace
local iregion = {}
---@class region: iregion
region = {}
---@return string
function iregion.name() return nil end
---@return RegionType
function iregion.type() return nil end
---@return boolean
function iregion.fire() return nil end
---@return boolean
function iregion.freeze() return nil end
---@return boolean
function iregion.protect() return nil end
---@return string
function iregion.loader() return nil end
---@alias TNTMode 'ALLOW' | 'DENY' | 'ONLY_TB'
---@class tnt
local tnt = {}
---@return TNTMode
function tnt.mode() return nil end
---@return boolean
function tnt.enabled() return nil end
---@return boolean
function tnt.onlyTb() return nil end
---@class trace
local trace = {}
---@return boolean
function trace.active() return nil end
---@return boolean
function trace.auto() return nil end
---@return string
function trace.status() return nil end
---@return number
function trace.time() return nil end
---@param name string
---@return iregion
function region.get(name) return nil end
---@return iregion[]
function region.list() return nil end
---@class Position
---@field x number
---@field y number
---@field z number
---@class server
---@field tps tps
server = {}
---@return string
function server.time() return nil end
---@return number
function server.ticks() return nil end
---@param position Position
---@return string
function getBlockAt(position) return nil end
---@param position Position
---@param material string
---@return void
function setBlockAt(position, material) return nil end
---@class tps
local tps = {}
---@return number
function tps.oneSecond() return nil end
---@return number
function tps.tenSecond() return nil end
---@return number
function tps.oneMinute() return nil end
---@return number
function tps.fiveMinute() return nil end
---@return number
function tps.tenMinute() return nil end
---@return number
function tps.current() return nil end
---@return number
function tps.limit() return nil end
---@class storage
---@field global storageLib
---@field player storageLib
---@field region storageLib
storage = {}
---@class storageLib
local storageLib = {}
---@param key string
---@return any
function storageLib.get(key) return nil end
---@param key string
---@param value any
---@return void
function storageLib.set(key, value) end
---@param key string
---@return boolean
function storageLib.has(key) return nil end
---@param key string
---@return void
function storageLib.remove(key) end
---@param key string
---@return Accessor
function storageLib.accessor(key) return nil end
---@class Accessor
---@overload fun(): any
---@overload fun(value: any)
---@class Selection
---@field max Position
---@field min Position
---@class _worldedit
_worldedit = {}
---@overload fun(pos: Position[]): void
---@return Selection
function _worldedit.selection() return nil end
---@param msg string
---@param callback fun(value: string): void
---@return void
function input(msg, callback) end
---@param ticks number
---@param callback fun(): void
---@return void
function delayed(ticks, callback) end
---@param x number
---@param y number
---@param z number
---@return Position
function pos(x, y, z) return nil end
---@return void
function exec(...) end
---@param obj any
---@return number
function length(obj) return 0 end
---@param separator string
---@param table any[]
---@return string
function join(separator, table) return "" end
---@class EventType
---@class events
---@field DoubleSwap EventType
---@field PlaceBlock EventType
---@field BreakBlock EventType
---@field RightClick EventType
---@field LeftClick EventType
---@field TNTSpawn EventType
---@field TNTExplode EventType
---@field TNTExplodeInBuild EventType
---@field SelfJoin EventType
---@field SelfLeave EventType
---@field DropItem EventType
---@field EntityDeath EventType
events = {}
---@param id EventType
---@param handler fun(params: any): void
---@return void
function event(id, handler) end
---@param command string
---@param handler fun(params: string[]): void
---@return void
function command(command, handler) end
---@param trigger string
---@param handler fun(pressed: boolean): void
---@return void
function hotkey(trigger, handler) end

Datei anzeigen

@ -0,0 +1,386 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.ai.navmesh;
import de.steamwar.entity.RArmorStand;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.OneShotStateDependent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.event.Listener;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
import org.bukkit.util.VoxelShape;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
public class NavMesh implements Listener {
private static final World WORLD = Bukkit.getWorlds().get(0);
private static final double PLAYER_JUMP_HEIGHT = 1.25;
private static final double PLAYER_HEIGHT = 1.8125;
private static final BoundingBox PLAYER_SHADOW = new BoundingBox(0.2, 0, 0.2, 0.8, 1, 0.8);
private static final Set<Pos> RELATIVE_BLOCKS_TO_CHECK = new HashSet<>();
static {
for (int y = -2; y <= 2; y++) {
RELATIVE_BLOCKS_TO_CHECK.add(new Pos(BlockFace.NORTH.getDirection().setY(y)));
RELATIVE_BLOCKS_TO_CHECK.add(new Pos(BlockFace.SOUTH.getDirection().setY(y)));
RELATIVE_BLOCKS_TO_CHECK.add(new Pos(BlockFace.EAST.getDirection().setY(y)));
RELATIVE_BLOCKS_TO_CHECK.add(new Pos(BlockFace.WEST.getDirection().setY(y)));
}
RELATIVE_BLOCKS_TO_CHECK.add(new Pos(BlockFace.UP.getDirection()));
RELATIVE_BLOCKS_TO_CHECK.add(new Pos(BlockFace.DOWN.getDirection()));
}
private FightTeam fightTeam;
private List<REntity> rEntities = new ArrayList<>();
private REntityServer entityServer;
public NavMesh(FightTeam fightTeam, REntityServer entityServer) {
this.fightTeam = fightTeam;
this.entityServer = entityServer;
new OneShotStateDependent(ArenaMode.All, FightState.PostSchemSetup, () -> {
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> {
long time = System.currentTimeMillis();
fightTeam.getExtendRegion().forEach((x, y, z) -> {
if (y < fightTeam.getSchemRegion().getMinY()) return;
checkWalkable(x, y, z);
});
floorBlock.forEach(this::checkNeighbouring);
System.out.println(System.currentTimeMillis() - time + " ms");
iterateWalkableBlocks((vector, ceilingOffset) -> {
RArmorStand armorStand = new RArmorStand(entityServer, vector.toLocation(WORLD), RArmorStand.Size.MARKER);
armorStand.setNoGravity(true);
armorStand.setInvisible(true);
armorStand.setDisplayName("+" + (ceilingOffset == null ? "" : ceilingOffset));
});
}, 20);
});
new OneShotStateDependent(ArenaMode.All, FightState.Spectate, () -> {
floorBlock.clear();
});
}
private static class Pos {
private int x;
private int y;
private int z;
public Pos(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Pos(Vector vector) {
this.x = vector.getBlockX();
this.y = vector.getBlockY();
this.z = vector.getBlockZ();
}
@Override
public String toString() {
return x + "," + y + "," + z;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Pos)) return false;
Pos pos = (Pos) o;
return x == pos.x && y == pos.y && z == pos.z;
}
@Override
public int hashCode() {
return Objects.hash(x, y, z);
}
public Vector toVector() {
return new Vector(x, y, z);
}
public Pos add(Pos pos) {
return new Pos(x + pos.x, y + pos.y, z + pos.z);
}
public Pos subtract(Pos pos) {
return new Pos(x - pos.x, y - pos.y, z - pos.z);
}
}
private Map<Pos, Double> floorBlock = new HashMap<>();
private Map<Pos, Double> ceilingOffset = new HashMap<>();
private Map<Pos, Set<Pos>> neighbourConnections = new HashMap<>();
private Map<Pos, Set<Pos>> reverseNeighbourConnections = new HashMap<>();
private void checkWalkable(int x, int y, int z) {
Pos pos = new Pos(x, y, z);
floorBlock.remove(pos);
ceilingOffset.remove(pos);
Block block = WORLD.getBlockAt(x, y, z);
VoxelShape floor = block.getCollisionShape();
if (block.getType() != Material.LADDER && !overlaps(floor, 0, 0, 0)) return;
Double floorHeight = null;
for (BoundingBox box : floor.getBoundingBoxes()) {
double by = box.getMaxY();
if (!overlaps(floor, 0, by, 0)) {
if (floorHeight == null) {
floorHeight = by;
} else {
floorHeight = Math.min(floorHeight, by);
}
}
}
if (floorHeight == null) return;
Double ceilingOffset = null;
for (int cy = y + 1; cy < fightTeam.getExtendRegion().getMaxY(); cy++) {
VoxelShape current = WORLD.getBlockAt(x, cy, z).getCollisionShape();
if (!overlaps(current, 0, 0, 0)) continue;
Double ceilingHeight = null;
for (BoundingBox box : current.getBoundingBoxes()) {
double by = box.getMinY();
if (!overlaps(current, 0, -(1 - by), 0)) {
if (ceilingHeight == null) {
ceilingHeight = by;
} else {
ceilingHeight = Math.max(ceilingHeight, by);
}
}
}
if (ceilingHeight != null) {
ceilingOffset = cy - y + ceilingHeight - floorHeight;
}
break;
}
if (ceilingOffset != null && ceilingOffset < PLAYER_HEIGHT) return;
floorBlock.put(pos, y + floorHeight);
this.ceilingOffset.put(pos, ceilingOffset);
}
private void checkNeighbouring(Pos pos, double posFloorHeight) {
Set<Pos> connections = neighbourConnections.remove(pos);
if (connections != null) {
connections.forEach(p -> {
reverseNeighbourConnections.getOrDefault(pos.add(p), Collections.emptySet()).remove(pos);
});
}
for (Pos relativeCheck : RELATIVE_BLOCKS_TO_CHECK) {
Pos other = new Pos(pos.x + relativeCheck.x, pos.y + relativeCheck.y, pos.z + relativeCheck.z);
Double otherFloorHeight = floorBlock.get(other);
if (otherFloorHeight == null) continue;
if (otherFloorHeight > posFloorHeight && otherFloorHeight - posFloorHeight > PLAYER_JUMP_HEIGHT) continue;
// double floorDiff = Math.abs(posFloorHeight - otherFloorHeight);
// if (floorDiff > PLAYER_JUMP_HEIGHT) continue;
Double posCeilingOffset = ceilingOffset.get(pos);
Double otherCeilingOffset = ceilingOffset.get(other);
if (posCeilingOffset == null && otherCeilingOffset == null) {
neighbourConnections.computeIfAbsent(pos, __ -> new LinkedHashSet<>()).add(relativeCheck);
reverseNeighbourConnections.computeIfAbsent(pos.add(relativeCheck), __ -> new LinkedHashSet<>()).add(pos);
continue;
}
if (posCeilingOffset != null && otherCeilingOffset == null) {
if (posFloorHeight + posCeilingOffset - otherFloorHeight >= PLAYER_HEIGHT) {
neighbourConnections.computeIfAbsent(pos, __ -> new LinkedHashSet<>()).add(relativeCheck);
reverseNeighbourConnections.computeIfAbsent(pos.add(relativeCheck), __ -> new LinkedHashSet<>()).add(pos);
}
continue;
}
if (otherCeilingOffset != null && posCeilingOffset == null) {
if (otherFloorHeight + otherCeilingOffset - posFloorHeight >= PLAYER_HEIGHT) {
neighbourConnections.computeIfAbsent(pos, __ -> new LinkedHashSet<>()).add(relativeCheck);
reverseNeighbourConnections.computeIfAbsent(pos.add(relativeCheck), __ -> new LinkedHashSet<>()).add(pos);
}
continue;
}
if (posFloorHeight + posCeilingOffset - otherFloorHeight >= PLAYER_HEIGHT && otherFloorHeight + otherCeilingOffset - posFloorHeight >= PLAYER_HEIGHT) {
neighbourConnections.computeIfAbsent(pos, __ -> new LinkedHashSet<>()).add(relativeCheck);
reverseNeighbourConnections.computeIfAbsent(pos.add(relativeCheck), __ -> new LinkedHashSet<>()).add(pos);
}
}
}
private boolean overlaps(VoxelShape voxelShape, double x, double y, double z) {
PLAYER_SHADOW.shift(x, y, z);
boolean overlaps = voxelShape.overlaps(PLAYER_SHADOW);
PLAYER_SHADOW.shift(-x, -y, -z);
return overlaps;
}
private void iterateWalkableBlocks(BiConsumer<Vector, Double> consumer) {
floorBlock.forEach((pos, aDouble) -> {
Vector vector = new Vector(pos.x + 0.5, aDouble, pos.z + 0.5);
consumer.accept(vector, ceilingOffset.get(pos));
});
}
private Pos toPos(Vector vector) {
Pos pos = new Pos(vector);
if (floorBlock.containsKey(pos)) return pos;
pos = new Pos(pos.x, pos.y - 1, pos.z);
if (floorBlock.containsKey(pos)) return pos;
return null;
}
public void update(Vector posVector) {
Pos pos = toPos(posVector);
if (pos == null) return;
for (int x = -2; x <= 2; x++) {
for (int z = -2; z <= 2; z++) {
for (int y = fightTeam.getSchemRegion().getMinY(); y <= pos.y + 2; y++) {
checkWalkable(pos.x + x, y, pos.z + z);
}
}
}
floorBlock.forEach(this::checkNeighbouring);
}
public List<Vector> getAllWalkableBlocks() {
return floorBlock.keySet().stream().map(Pos::toVector).collect(Collectors.toList());
}
public List<Vector> getWalkableBlocks(Vector fromVector) {
Pos from = toPos(fromVector);
if (from == null) {
return Collections.emptyList();
}
Set<Pos> checked = new HashSet<>();
List<Pos> checking = new ArrayList<>();
checking.add(from);
while (!checking.isEmpty()) {
Pos pos = checking.remove(0);
checked.add(pos);
neighbourConnections.getOrDefault(pos, new HashSet<>()).forEach(p -> {
Pos n = pos.add(p);
if (checked.contains(n)) return;
if (checking.contains(n)) return;
checking.add(n);
});
}
return checked.stream().map(Pos::toVector).collect(Collectors.toList());
}
public List<Vector> path(Vector fromVector, Vector toVector) {
rEntities.forEach(REntity::die);
rEntities.clear();
Pos from = toPos(fromVector);
Pos to = toPos(toVector);
if (from == null || to == null) {
return Collections.emptyList();
}
if (from.equals(to)) {
return Collections.emptyList();
}
List<Pos> checking = new ArrayList<>(Arrays.asList(to));
Map<Pos, Pos> route = new HashMap<>();
while (!checking.isEmpty()) {
Set<Pos> toCheck = new HashSet<>();
for (Pos pos : checking) {
boolean foundFrom = false;
Set<Pos> successors = reverseNeighbourConnections.get(pos);
for (Pos p : successors) {
if (route.containsKey(p)) continue;
route.put(p, pos);
toCheck.add(p);
foundFrom = p.equals(from);
if (foundFrom) break;
}
if (foundFrom) {
List<Pos> path = new ArrayList<>();
path.add(from);
while (path.get(path.size() - 1) != to) {
path.add(route.get(path.get(path.size() - 1)));
}
for (int i = path.size() - 1; i > 0; i--) {
Pos current = path.get(i);
Pos last = path.get(i - 1);
if (last.y > current.y) {
path.set(i, new Pos(current.x, last.y, current.z));
}
}
List<Vector> vectors = path.stream().map(p -> {
Double floorHeight = floorBlock.get(p);
if (p.y > (floorHeight == null ? p.y : floorHeight)) floorHeight = null;
return new Vector(p.x + 0.5, floorHeight == null ? p.y : floorHeight, p.z + 0.5);
}).collect(Collectors.toList());
AtomicReference<Vector> last = new AtomicReference<>();
vectors.forEach(vector -> {
RArmorStand armorStand = new RArmorStand(entityServer, vector.toLocation(WORLD), RArmorStand.Size.MARKER);
armorStand.setInvisible(true);
armorStand.setNoGravity(true);
armorStand.setDisplayName("+");
rEntities.add(armorStand);
if (true) return;
Vector lastVector = last.getAndSet(vector);
if (lastVector == null) return;
lastVector = lastVector.clone().add(vector).divide(new Vector(2, 2, 2));
armorStand = new RArmorStand(entityServer, lastVector.toLocation(WORLD), RArmorStand.Size.MARKER);
armorStand.setInvisible(true);
armorStand.setNoGravity(true);
armorStand.setDisplayName("+");
rEntities.add(armorStand);
});
return vectors;
}
}
checking.clear();
checking.addAll(toCheck);
}
return Collections.emptyList();
}
}

Datei anzeigen

@ -0,0 +1,42 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.commands;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.SimpleCommandMap;
import java.lang.reflect.Field;
public class CommandInjector {
private CommandInjector(){}
private static final String PACKAGE_NAME = Bukkit.getServer().getClass().getPackage().getName();
private static final String VERSION = PACKAGE_NAME.substring(PACKAGE_NAME.lastIndexOf('.') + 1);
public static void injectCommand(Command cmd) throws Exception {
Class serverClass = Class.forName("org.bukkit.craftbukkit." + VERSION + ".CraftServer");
Field f1 = serverClass.getDeclaredField("commandMap");
f1.setAccessible(true);
SimpleCommandMap commandMap = (SimpleCommandMap) f1.get(Bukkit.getServer());
commandMap.register("BauSystem", cmd);
}
}

Datei anzeigen

@ -19,7 +19,6 @@
package de.steamwar.fightsystem.commands;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.Fight;
@ -29,20 +28,12 @@ import de.steamwar.fightsystem.fight.Kit;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.sql.PersonalKit;
import de.steamwar.sql.SteamwarUser;
import lombok.experimental.UtilityClass;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.entity.Player;
@UtilityClass
public class Commands {
private static final Reflection.FieldAccessor<SimpleCommandMap> commandMap = Reflection.getField("{obc}.CraftServer", "commandMap", SimpleCommandMap.class);
public static void injectCommand(Command cmd) {
commandMap.get(Bukkit.getServer()).register("FightSystem", cmd);
}
private Commands(){}
private static void errNoTeam(Player p){
FightSystem.getMessage().sendPrefixless("NO_TEAM", p, ChatMessageType.ACTION_BAR);

Datei anzeigen

@ -19,7 +19,6 @@
package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.*;
@ -30,7 +29,6 @@ import de.steamwar.inventory.*;
import de.steamwar.message.Message;
import de.steamwar.sql.PersonalKit;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SchematicType;
import de.steamwar.sql.SteamwarUser;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Bukkit;
@ -50,8 +48,7 @@ public class GUI {
@SuppressWarnings("deprecation")
private static void addTeamRequest(Player p, SWInventory inv, int pos, FightTeam team) {
byte colorCode = ColorConverter.chat2dye(team.getColor()).getDyeData();
String name = team.getLeader() != null ? team.getLeader().getEntity().getName() : team.getName();
inv.setItem(pos, SWItem.getDye(colorCode), colorCode, msg.parse("JOIN_REQUEST_TEAM", p, team.getColor() + name), click -> {
inv.setItem(pos, SWItem.getDye(colorCode), colorCode, msg.parse("JOIN_REQUEST_TEAM", p, team.getColoredName()), click -> {
p.closeInventory();
new JoinRequest(p, team);
});
@ -170,47 +167,27 @@ public class GUI {
return;
}
int invSize = (Config.SubTypes.size() + 1) * 9;
SWInventory inv = new SWInventory(p, invSize, msg.parse("SCHEM_TITLE", p, Config.GameName));
setupSchemTypeRow(p, inv, Config.SchematicType, 0);
for (int i = 0; i < Config.SubTypes.size(); i++) {
setupSchemTypeRow(p, inv, Config.SubTypes.get(i), i + 1);
SWInventory inv = new SWInventory(p, 9, msg.parse("SCHEM_TITLE", p, Config.GameName));
inv.setItem(8, Material.REDSTONE, msg.parse("SCHEM_PUBLIC", p, Config.GameName), (ClickType click) -> {
p.closeInventory();
schemDialog(p, true);
});
if(Fight.getMaxRank() == 0){
inv.setItem(0, SWItem.getDye(8), (byte)8, msg.parse("SCHEM_PRIVATE_FORBIDDEN", p, Config.GameName), (ClickType click)->{});
}else if(SchematicNode.getAllAccessibleSchematicsOfType(SteamwarUser.get(p.getUniqueId()).getId(), Config.SchematicType.toDB()).isEmpty() && !Config.test()){
inv.setItem(0, SWItem.getDye(8), (byte)8, msg.parse("SCHEM_NO_PRIVATE", p, Config.GameName), (ClickType click)->{});
}else{
inv.setItem(0, SWItem.getMaterial("CAULDRON_ITEM"), msg.parse("SCHEM_PRIVATE", p, Config.GameName), (ClickType click) -> {
p.closeInventory();
schemDialog(p, false);
});
}
inv.setCallback(-999, (ClickType click) -> p.closeInventory());
inv.open();
}
private static void setupSchemTypeRow(Player p, SWInventory inv, SchematicType type, int row) {
inv.setItem(row * 9 + 8, Material.REDSTONE, msg.parse("SCHEM_PUBLIC", p, type.name()), (ClickType click) -> {
p.closeInventory();
schemDialog(p, type, true, false);
});
if (Fight.publicOnly()) {
inv.setItem(row * 9, SWItem.getDye(8), (byte)8, msg.parse("SCHEM_PRIVATE_FORBIDDEN", p, type.name()), (ClickType click)->{});
return;
}
if (type.checkType() != null && type.checkType() != type && ArenaMode.AntiEvent.contains(Config.mode) && !SchematicNode.getAllAccessibleSchematicsOfType(SteamwarUser.get(p.getUniqueId()).getId(), type.checkType().toDB()).isEmpty()) {
inv.setItem(row * 9 + 4, Material.ANVIL, msg.parse("SCHEM_UNCHECKED", p, type.name()), (ClickType click) -> {
p.closeInventory();
schemDialog(p, type, false, true);
});
}
if (SchematicNode.getAllAccessibleSchematicsOfType(SteamwarUser.get(p.getUniqueId()).getId(), type.toDB()).isEmpty() && !Config.test()) {
inv.setItem(row * 9, SWItem.getDye(8), (byte)8, msg.parse("SCHEM_NO_PRIVATE", p, type.name()), (ClickType click)->{});
return;
}
inv.setItem(row * 9, SWItem.getMaterial("CAULDRON_ITEM"), msg.parse("SCHEM_PRIVATE", p, type.name()), (ClickType click) -> {
p.closeInventory();
schemDialog(p, type, false, false);
});
}
private static void schemDialog(Player p, SchematicType type, boolean publicSchems, boolean unchecked){
SchematicSelector selector = new SchematicSelector(p, Config.test() ? SchematicSelector.selectSchematic() : SchematicSelector.selectSchematicType(unchecked ? type.checkType() : type), node -> {
private static void schemDialog(Player p, boolean publicSchems){
SchematicSelector selector = new SchematicSelector(p, Config.test()?SchematicSelector.selectSchematic():SchematicSelector.selectSchematicTypeWithRank(Config.SchematicType, Fight.getMaxRank()), node -> {
FightTeam fightTeam = Fight.getPlayerTeam(p);
if(fightTeam == null)
return;

Datei anzeigen

@ -47,10 +47,10 @@ public class GamemodeCommand extends BukkitCommand {
try {
CommandRemover.removeAll("gamemode");
CommandInjector.injectCommand(this);
} catch (Exception e) {
FightSystem.getPlugin().getLogger().log(Level.SEVERE, "Failed to replace commands", e);
}
Commands.injectCommand(this);
}
@Override

Datei anzeigen

@ -35,7 +35,7 @@ import org.bukkit.entity.Player;
public class LockschemCommand implements CommandExecutor {
public LockschemCommand() {
new StateDependentCommand(ArenaMode.All, FightState.Schem, "lockschem", this);
new StateDependentCommand(ArenaMode.AntiReplay, FightState.All, "lockschem", this);
}
@Override

Datei anzeigen

@ -1,52 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.commands;
import de.steamwar.core.TPSWarpUtils;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
public class TPSWarpCommand implements CommandExecutor {
public TPSWarpCommand() {
new StateDependentCommand(ArenaMode.Prepare, FightState.PostSchemSetup, "tpswarp", this);
new StateDependentCommand(ArenaMode.Prepare, FightState.PostSchemSetup, "tpslimit", this);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
double tps;
try {
tps = Double.parseDouble(args[0]);
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
FightSystem.getMessage().send("TPSWARP_HELP", sender);
return false;
}
TPSWarpUtils.warp(tps);
FightSystem.getMessage().broadcastActionbar("TPSWARP_SET", tps);
return false;
}
}

Datei anzeigen

@ -83,6 +83,8 @@ public abstract class Countdown {
}
for(Countdown countdown : new ArrayList<>(currentCountdowns)) {
if(countdown.time - smallestTime <= 1)
countdown.prepareFinish();
countdown.time -= smallestTime;
countdown.show();
}
@ -102,6 +104,8 @@ public abstract class Countdown {
Bukkit.getOnlinePlayers().forEach(p -> sendCountdownMessage(p, message, time / divisor, appendix));
}
protected void prepareFinish() {}
public int getTimeLeft(){
return time;
}
@ -120,6 +124,7 @@ public abstract class Countdown {
broadcast("COUNTDOWN_SECONDS", 1);
break;
case 1:
prepareFinish();
broadcast("COUNTDOWN_SECOND", 1);
break;
case 0:

Datei anzeigen

@ -21,23 +21,21 @@ package de.steamwar.fightsystem.countdown;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.events.BoardingEvent;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightPlayer;
import de.steamwar.fightsystem.utils.Message;
import de.steamwar.fightsystem.utils.Region;
import de.steamwar.fightsystem.utils.SWSound;
import de.steamwar.techhider.ProtocolUtils;
import de.steamwar.fightsystem.winconditions.Wincondition;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Bukkit;
import java.util.List;
public class EnternCountdown extends Countdown {
private static int calcTime(FightPlayer fp, Countdown countdown) {
private static int calcTime(FightPlayer fp) {
int time = Config.EnterStages.get(fp.getKit().getEnterStage());
Countdown countdown = Wincondition.getTimeOverCountdown();
if(countdown != null) {
time -= Config.TimeoutTime - countdown.getTimeLeft();
@ -51,20 +49,21 @@ public class EnternCountdown extends Countdown {
private final FightPlayer fightPlayer;
private List<ProtocolUtils.ChunkPos> chunkPos;
public EnternCountdown(FightPlayer fp, Countdown countdown) {
super(calcTime(fp, countdown), new Message("ENTERN_COUNTDOWN"), SWSound.BLOCK_NOTE_PLING, false);
public EnternCountdown(FightPlayer fp) {
super(calcTime(fp), new Message("ENTERN_COUNTDOWN"), SWSound.BLOCK_NOTE_PLING, false);
fightPlayer = fp;
enable();
}
@Override
public void countdownFinished() {
Bukkit.getPluginManager().callEvent(new BoardingEvent(fightPlayer));
FightSystem.getMessage().sendPrefixless("ENTERN_ALLOWED", fightPlayer.getEntity(), ChatMessageType.ACTION_BAR);
fightPlayer.ifPlayer(player -> {
FightSystem.getHullHider().updatePlayer(player);
FightSystem.getTechHider().reloadChunks(player, Fight.getOpposite(fightPlayer.getTeam()).getExtendRegion(), Region.EMPTY);
});
fightPlayer.ifPlayer(player -> FightSystem.getTechHider().reloadChunks(player, chunkPos, false));
}
@Override
protected void prepareFinish() {
chunkPos = FightSystem.getTechHider().prepareChunkReload(fightPlayer.getEntity(), false);
}
@Override

Datei anzeigen

@ -1,49 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.event;
import com.sk89q.worldedit.WorldEditException;
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.OneShotStateDependent;
import de.steamwar.fightsystem.utils.WorldeditWrapper;
import de.steamwar.fightsystem.winconditions.Winconditions;
import de.steamwar.sql.SchematicNode;
import java.util.logging.Level;
public class PersistentDamage {
public PersistentDamage() {
if(!ArenaMode.SeriousFight.contains(Config.mode))
return;
new OneShotStateDependent(Winconditions.PERSISTENT_DAMAGE, FightState.Spectate, () -> Fight.teams().forEach(team -> {
try{
WorldeditWrapper.impl.saveSchem(SchematicNode.getSchematicNode(team.getSchematic()), team.getExtendRegion(), team.getSchemRegion().getMinY());
}catch(WorldEditException e){
FightSystem.getPlugin().getLogger().log(Level.SEVERE, "Could not persist schematic state", e);
}
}));
}
}

Datei anzeigen

@ -1,40 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.events;
import de.steamwar.fightsystem.fight.FightPlayer;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@Getter
@AllArgsConstructor
public class BoardingEvent extends Event {
@Getter
private static final HandlerList handlerList = new HandlerList();
private final FightPlayer fightPlayer;
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

Datei anzeigen

@ -1,40 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.events;
import de.steamwar.fightsystem.fight.FightPlayer;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@Getter
@AllArgsConstructor
public class TeamDeathEvent extends Event {
@Getter
private static final HandlerList handlerList = new HandlerList();
private final FightPlayer fightPlayer;
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

Datei anzeigen

@ -1,40 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.events;
import de.steamwar.fightsystem.fight.FightPlayer;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@Getter
@AllArgsConstructor
public class TeamLeaveEvent extends Event {
@Getter
private static final HandlerList handlerList = new HandlerList();
private final FightPlayer fightPlayer;
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

Datei anzeigen

@ -1,40 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.events;
import de.steamwar.fightsystem.fight.FightPlayer;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@Getter
@AllArgsConstructor
public class TeamSpawnEvent extends Event {
@Getter
private static final HandlerList handlerList = new HandlerList();
private final FightPlayer fightPlayer;
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

Datei anzeigen

@ -21,13 +21,11 @@ package de.steamwar.fightsystem.fight;
import com.comphenix.tinyprotocol.TinyProtocol;
import com.mojang.authlib.GameProfile;
import de.steamwar.core.Core;
import de.steamwar.core.ProtocolWrapper;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.record.GlobalRecorder;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Sound;
@ -40,9 +38,7 @@ import java.util.HashSet;
public class Fight {
private Fight(){}
@Getter
private static final FightTeam redTeam = new FightTeam(Config.TeamRedName, Config.TeamRedColor, Config.TeamRedSpawn, Config.RedPasteRegion, Config.RedExtendRegion, Config.RedRotate, false, Config.RedLeader);
@Getter
private static final FightTeam blueTeam = new FightTeam(Config.TeamBlueName, Config.TeamBlueColor, Config.TeamBlueSpawn, Config.BluePasteRegion, Config.BlueExtendRegion, Config.BlueRotate, true, Config.BlueLeader);
private static final Collection<FightTeam> teams = new HashSet<>();
static {
@ -79,6 +75,14 @@ public class Fight {
return getPlayerTeam(player) != null;
}
public static FightTeam getRedTeam() {
return redTeam;
}
public static FightTeam getBlueTeam() {
return blueTeam;
}
public static Collection<FightTeam> teams() {
return teams;
}
@ -90,10 +94,7 @@ public class Fight {
public static void playSound(Sound sound, float volume, float pitch) {
GlobalRecorder.getInstance().soundAtPlayer(sound.name(), volume, pitch);
//volume: max. 100, pitch: max. 2
if(Core.getVersion() >= 18)
Bukkit.getServer().getOnlinePlayers().forEach(player -> player.playSound(player, sound, volume, pitch));
else
Bukkit.getServer().getOnlinePlayers().forEach(player -> player.playSound(player.getLocation(), sound, volume, pitch));
Bukkit.getServer().getOnlinePlayers().forEach(player -> player.playSound(player.getLocation(), sound, volume, pitch));
}
public static FightTeam getTeamByName(String name) {
@ -123,7 +124,7 @@ public class Fight {
if(!player.isOnline())
return;
pseudoSpectator(player, true);
}, 1);
}, 2);
}else if(gameMode == GameMode.SURVIVAL) {
for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) {
if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) {
@ -138,16 +139,21 @@ public class Fight {
TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.GAMEMODE, new GameProfile(player.getUniqueId(), player.getName()), enable ? GameMode.CREATIVE : GameMode.SPECTATOR));
}
public static boolean publicOnly() {
if (Config.OnlyPublicSchematics) {
return true;
public static int getMaxRank(){
/* MaxRank of 0 is Pubonly*/
if(Config.OnlyPublicSchematics){
return 0;
}
if (Config.IgnorePublicOnly || ArenaMode.RankedEvent.contains(Config.mode)) {
return false;
if(Config.IgnorePublicOnly || ArenaMode.RankedEvent.contains(Config.mode)){
return 1000;
}
if (redTeam.getLeader() == null || blueTeam.getLeader() == null) {
return false;
if(redTeam.getLeader() == null || blueTeam.getLeader() == null){
return 1000;
}
return redTeam.isPublicsOnly() || blueTeam.isPublicsOnly();
return Math.min(redTeam.getSchemRank(), blueTeam.getSchemRank());
}
}

Datei anzeigen

@ -21,13 +21,9 @@ package de.steamwar.fightsystem.fight;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.ai.AI;
import de.steamwar.fightsystem.countdown.Countdown;
import de.steamwar.fightsystem.countdown.EnternCountdown;
import de.steamwar.fightsystem.events.TeamDeathEvent;
import de.steamwar.sql.PersonalKit;
import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@ -38,13 +34,9 @@ public class FightPlayer {
private final int id;
private LivingEntity entity;
@Getter
private final FightTeam team;
private boolean isOut;
@Setter
@Getter
private Kit kit;
@Getter
private int kills;
private EnternCountdown enternCountdown = null;
@ -69,14 +61,13 @@ public class FightPlayer {
public void setOut() {
isOut = true;
Bukkit.getPluginManager().callEvent(new TeamDeathEvent(this));
stopEnternCountdown();
ifAI(AI::stop);
}
public void startEnternCountdown(Countdown countdown) {
public void startEnternCountdown() {
if(Config.EnterStages.size() > kit.getEnterStage() && kit.getEnterStage() >= 0)
enternCountdown = new EnternCountdown(this, countdown);
enternCountdown = new EnternCountdown(this);
}
public void stopEnternCountdown(){
@ -119,6 +110,22 @@ public class FightPlayer {
return leader != null && leader.getEntity() == entity;
}
public Kit getKit() {
return kit;
}
public void setKit(Kit kit) {
this.kit = kit;
}
public FightTeam getTeam(){
return team;
}
public int getKills(){
return kills;
}
public void addKill(){
kills++;
}

Datei anzeigen

@ -33,7 +33,6 @@ import de.steamwar.fightsystem.utils.Region;
import de.steamwar.fightsystem.utils.WorldeditWrapper;
import de.steamwar.sql.SchematicData;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SchematicType;
import org.bukkit.Bukkit;
import org.bukkit.DyeColor;
import org.bukkit.Location;
@ -101,17 +100,8 @@ public class FightSchematic extends StateDependent {
if(clipboard == null){
List<SchematicNode> publics = SchematicNode.getAllSchematicsOfType(0, Config.SchematicType.toDB());
if(publics.isEmpty()) {
for (SchematicType type : Config.SubTypes) {
publics = SchematicNode.getAllSchematicsOfType(0, type.toDB());
if (!publics.isEmpty()) {
break;
}
}
if (publics.isEmpty()) {
return;
}
}
if(publics.isEmpty())
return;
setSchematic(publics.get(new Random().nextInt(publics.size())));
}
@ -148,9 +138,6 @@ public class FightSchematic extends StateDependent {
).add(new Vector(rotate ? 1 : 0, 0, rotate ? 1 : 0)),
new AffineTransform().rotateY(rotate ? 180 : 0)
);
FightSystem.getHullHider().initialize(team);
if(ArenaMode.Check.contains(Config.mode) && !team.isBlue())
replaceSync(Material.TNT, Material.OBSIDIAN);
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), freezer::disable, 3);
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), team::teleportToSpawn, 40);
@ -200,7 +187,7 @@ public class FightSchematic extends StateDependent {
}
length -= 1;
AffineTransform aT = new AffineTransform().rotateY(((team == Fight.getRedTeam()) == (Config.BlueToRedZ > 0)) ? 180 : 0);
AffineTransform aT = new AffineTransform().rotateY(rotate ? 180 : 0);
Location base = new Location(Config.world, region.centerX(), team.getExtendRegion().getMaxY(), region.centerZ());
for(int i = 0; i < characters.length; i++){
WorldeditWrapper.impl.pasteClipboard(characters[i], base, new Vector(offsets[i] - length/2, 0, -region.getSizeZ()/2), aT);

Datei anzeigen

@ -25,24 +25,22 @@ import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.commands.GUI;
import de.steamwar.fightsystem.countdown.Countdown;
import de.steamwar.fightsystem.events.TeamLeaveEvent;
import de.steamwar.fightsystem.events.TeamSpawnEvent;
import de.steamwar.fightsystem.listener.FightScoreboard;
import de.steamwar.fightsystem.listener.Permanent;
import de.steamwar.fightsystem.listener.PersonalKitCreator;
import de.steamwar.fightsystem.listener.TeamArea;
import de.steamwar.fightsystem.record.GlobalRecorder;
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.Wincondition;
import de.steamwar.fightsystem.winconditions.Winconditions;
import de.steamwar.inventory.SWItem;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import de.steamwar.techhider.ProtocolUtils;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.*;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.NameTagVisibility;
@ -56,7 +54,7 @@ public class FightTeam {
private static void setKitButton(HotbarKit kit, boolean leader) {
if (Kit.getAvailableKits(leader).size() > 1 || Config.PersonalKits)
kit.setItem(1, "CHOOSE_KIT", new ItemBuilder(Material.LEATHER_CHESTPLATE).enchant().build(), player -> GUI.kitSelection(player, ""));
kit.setItem(1, "CHOOSE_KIT", new ItemBuilder(Material.LEATHER_CHESTPLATE).removeAllAttributes().addEnchantment(Enchantment.DURABILITY, 1).build(), player -> GUI.kitSelection(player, ""));
else
kit.setItem(1, null, null, null);
}
@ -64,61 +62,50 @@ public class FightTeam {
private static final HotbarKit memberKit = new HotbarKit();
static {
setKitButton(memberKit, false);
memberKit.setItem(7, "RESPAWN", new ItemBuilder(Material.BEACON).build(), player -> player.teleport(Objects.requireNonNull(Fight.getPlayerTeam(player)).getSpawn()));
memberKit.setItem(7, "RESPAWN", new ItemBuilder(Material.BEACON).removeAllAttributes().build(), player -> player.teleport(Objects.requireNonNull(Fight.getPlayerTeam(player)).getSpawn()));
}
private static final HotbarKit notReadyKit = new HotbarKit(memberKit);
static {
setKitButton(notReadyKit, true);
if(!ArenaMode.RankedEvent.contains(Config.mode)){
notReadyKit.setItem(2, "REQUESTS", new ItemBuilder(Material.PAPER).build(), GUI::chooseJoinRequests);
notReadyKit.setItem(3, "REMOVE_PLAYERS", new ItemBuilder(SWItem.getMaterial("FIREWORK_CHARGE")).build(), GUI::chooseRemove);
notReadyKit.setItem(2, "REQUESTS", new ItemBuilder(Material.PAPER).removeAllAttributes().build(), GUI::chooseJoinRequests);
notReadyKit.setItem(3, "REMOVE_PLAYERS", new ItemBuilder(SWItem.getMaterial("FIREWORK_CHARGE")).removeAllAttributes().build(), GUI::chooseRemove);
}
if(Config.test())
notReadyKit.setItem(5, "CHOOSE_SCHEMATIC", new ItemBuilder(SWItem.getMaterial("CAULDRON_ITEM")).enchant().build(), GUI::preSchemDialog);
notReadyKit.setItem(5, "CHOOSE_SCHEMATIC", new ItemBuilder(SWItem.getMaterial("CAULDRON_ITEM")).removeAllAttributes().addEnchantment(Enchantment.DURABILITY, 1).build(), GUI::preSchemDialog);
notReadyKit.setItem(4, "TEAM_NOT_READY", new ItemBuilder(SWItem.getDye(10), (short) 10).enchant().build(), player -> Objects.requireNonNull(Fight.getPlayerTeam(player)).setReady(true));
notReadyKit.setItem(4, "TEAM_NOT_READY", new ItemBuilder(SWItem.getDye(10), (short) 10).removeAllAttributes().addEnchantment(Enchantment.DURABILITY, 1).build(), player -> Objects.requireNonNull(Fight.getPlayerTeam(player)).setReady(true));
}
private static final HotbarKit chooseSchemKit = new HotbarKit(notReadyKit);
static {
chooseSchemKit.setItem(4, "CHOOSE_SCHEMATIC", new ItemBuilder(SWItem.getMaterial("CAULDRON_ITEM")).enchant().build(), GUI::preSchemDialog);
chooseSchemKit.setItem(4, "CHOOSE_SCHEMATIC", new ItemBuilder(SWItem.getMaterial("CAULDRON_ITEM")).removeAllAttributes().addEnchantment(Enchantment.DURABILITY, 1).build(), GUI::preSchemDialog);
}
private static final HotbarKit readyKit = new HotbarKit(memberKit);
static {
readyKit.setItem(1, null, null, null);
readyKit.setItem(4, "TEAM_READY", new ItemBuilder(SWItem.getDye(8), (short) 8).enchant().build(), player -> Objects.requireNonNull(Fight.getPlayerTeam(player)).setReady(false));
readyKit.setItem(4, "TEAM_READY", new ItemBuilder(SWItem.getDye(8), (short) 8).removeAllAttributes().addEnchantment(Enchantment.DURABILITY,1 ).build(), player -> Objects.requireNonNull(Fight.getPlayerTeam(player)).setReady(false));
}
@Getter
private UUID designatedLeader;
@Getter
private FightPlayer leader;
@Getter
private boolean publicsOnly;
private int schemRank;
private final Map<UUID, FightPlayer> players = new HashMap<>();
@Getter
private String name;
@Getter
private String prefix;
@Getter
private ChatColor color;
private final FightSchematic schematic;
private final Team team;
@Getter
private final boolean blue;
@Getter
private boolean ready;
private boolean skip;
@Getter
private final Location spawn;
@Getter
private final Region schemRegion;
@Getter
private final Region extendRegion;
@SuppressWarnings("deprecation")
@ -126,7 +113,7 @@ public class FightTeam {
this.spawn = spawn;
this.schemRegion = schemRegion;
this.extendRegion = extendRegion;
this.publicsOnly = false;
this.schemRank = 0;
this.ready = false;
this.skip = false;
this.blue = blue;
@ -135,7 +122,6 @@ public class FightTeam {
this.schematic = new FightSchematic(this, rotate);
new KitLoader();
new SpectateHandler();
new TeamArea(this);
team = FightScoreboard.getBukkitTeam(name);
WorldOfColorWrapper.impl.setTeamColor(team, color);
@ -159,10 +145,26 @@ public class FightTeam {
this.color = ChatColor.getByChar(ChatColor.getLastColors(prefix).replace("§", ""));
}
public UUID getDesignatedLeader(){
return designatedLeader;
}
public Region getSchemRegion() {
return schemRegion;
}
public Region getExtendRegion() {
return extendRegion;
}
public boolean canbeLeader(Player p){
return isLeaderless() && (designatedLeader == null || designatedLeader.equals(p.getUniqueId()));
}
public int getSchemRank() {
return schemRank;
}
public void teleportToSpawn(){
players.forEach((player, fp) -> fp.getEntity().teleport(spawn));
}
@ -200,16 +202,13 @@ public class FightTeam {
schematic.reset();
Set<UUID> playerSet = new HashSet<>(players.keySet());
playerSet.removeIf(uuid -> {
for(UUID uuid : playerSet){
Player player = Bukkit.getPlayer(uuid);
if(player == null) {
if(player == null)
removePlayer(players.get(uuid).getEntity());
return true;
}
return false;
});
}
FightPlayer leaderBackup = leader;
playerSet.removeIf(uuid -> Bukkit.getPlayer(uuid) == null);
players.clear();
leader = null;
@ -261,11 +260,10 @@ public class FightTeam {
}
public void addMember(LivingEntity entity, SteamwarUser user, boolean silent) {
final List<ProtocolUtils.ChunkPos> chunksToReload = FightSystem.getTechHider().prepareChunkReload(entity, false);
FightPlayer fightPlayer = getFightPlayer(entity) != null ? getFightPlayer(entity) : new FightPlayer(entity, user, this);
fightPlayer.revive();
players.put(entity.getUniqueId(), fightPlayer);
Bukkit.getPluginManager().callEvent(new TeamSpawnEvent(fightPlayer));
Permanent.getSpectatorTeam().removeEntry(entity.getName());
team.addEntry(entity.getName());
@ -276,7 +274,6 @@ public class FightTeam {
BountifulWrapper.impl.setAttackSpeed(player);
player.setFoodLevel(20);
player.getInventory().clear();
FightSystem.getHullHider().updatePlayer(player);
if(FightState.Spectate.contains(FightState.getFightState())) {
Fight.setPlayerGamemode(player, GameMode.SPECTATOR);
@ -287,9 +284,10 @@ public class FightTeam {
});
if(FightState.Running.contains(FightState.getFightState()))
fightPlayer.startEnternCountdown(Wincondition.getTimeOverCountdown());
fightPlayer.startEnternCountdown();
fightPlayer.ifPlayer(player -> FightSystem.getTechHider().reloadChunks(player, Config.ArenaRegion, fightPlayer.canEntern() ? Region.EMPTY : Fight.getOpposite(this).getExtendRegion()));
GlobalRecorder.getInstance().playerJoins(entity, user);
fightPlayer.ifPlayer(player -> FightSystem.getTechHider().reloadChunks(player, chunksToReload, false));
if(isLeaderless())
setLeader(fightPlayer, silent);
@ -299,9 +297,9 @@ public class FightTeam {
public void removePlayer(LivingEntity entity) {
FightPlayer fightPlayer = getFightPlayer(entity);
Bukkit.getPluginManager().callEvent(new TeamLeaveEvent(fightPlayer));
fightPlayer.ifPlayer(PersonalKitCreator::closeIfInKitCreator);
List<ProtocolUtils.ChunkPos> chunksToReload = FightSystem.getTechHider().prepareChunkReload(entity, true);
players.remove(entity.getUniqueId());
team.removeEntry(entity.getName());
Permanent.getSpectatorTeam().addEntry(entity.getName());
@ -311,6 +309,7 @@ public class FightTeam {
if(fightPlayer.equals(leader))
removeLeader();
GlobalRecorder.getInstance().entityDespawns(entity);
entity.teleport(Config.SpecSpawn);
fightPlayer.ifPlayer(player -> {
@ -318,8 +317,7 @@ public class FightTeam {
player.getInventory().clear();
if(player.isOnline()){
FightSystem.getHullHider().updatePlayer(player);
FightSystem.getTechHider().reloadChunks(player, Config.ArenaRegion, Fight.getOpposite(this).getExtendRegion());
FightSystem.getTechHider().reloadChunks(player, chunksToReload, true);
if(ArenaMode.VariableTeams.contains(Config.mode))
HotbarKit.SPECTATOR_KIT.loadToPlayer(player);
@ -331,6 +329,14 @@ public class FightTeam {
return leader == null;
}
public boolean isBlue(){
return blue;
}
public FightPlayer getLeader() {
return leader;
}
private void removeLeader() {
this.leader = null;
if(!players.isEmpty()) {
@ -351,7 +357,11 @@ public class FightTeam {
if(!silent)
FightUI.addSubtitle("UI_LEADER_JOINS", prefix, leader.getEntity().getName());
publicsOnly = SchematicNode.getAllAccessibleSchematicsOfType(leader.getUser().getId(), Config.SchematicType.toDB()).isEmpty();
Optional<Integer> maxRank = SchematicNode.getAllAccessibleSchematicsOfType(leader.getUser().getId(), Config.SchematicType.toDB()).stream().map(SchematicNode::getRank).max(Integer::compare);
if(Config.RanksEnabled)
schemRank = maxRank.orElse(1);
else
schemRank = maxRank.isPresent() ? 1 : 0;
if(!Config.PersonalKits)
leader.setKit(Kit.getKitByName(Config.LeaderDefault));
@ -374,16 +384,15 @@ public class FightTeam {
return players.values();
}
public boolean isReady() {
return ready;
}
public void pasteSchem() {
testPasteAction();
}
public void pasteSchem(SchematicNode schematic){
if(schematic.getSchemtype().check()) {
FightStatistics.unrank();
FightSystem.getMessage().broadcast("SCHEMATIC_UNCHECKED", getColoredName());
}
setSchem(schematic);
testPasteAction();
}
@ -444,14 +453,26 @@ public class FightTeam {
}
}
public String getName() {
return name;
}
public String getColoredName() {
return prefix + name;
}
public String getPrefix() {
return prefix;
}
public int getSchematic() {
return schematic.getId();
}
public Location getSpawn() {
return spawn;
}
public double getCurrentHearts() {
return players.values().stream().filter(FightPlayer::isLiving).mapToDouble(fp -> fp.getEntity().getHealth()).sum();
}
@ -469,6 +490,10 @@ public class FightTeam {
return (int) players.values().stream().filter(FightPlayer::isLiving).count();
}
public ChatColor getColor() {
return color;
}
@Override
public String toString() {
return name;

Datei anzeigen

@ -21,13 +21,11 @@ package de.steamwar.fightsystem.fight;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.listener.Recording;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependent;
import de.steamwar.fightsystem.utils.CraftbukkitWrapper;
import de.steamwar.fightsystem.utils.FlatteningWrapper;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldCreator;
@ -41,8 +39,11 @@ import java.util.Objects;
public class FightWorld extends StateDependent {
@Getter
private static final boolean PAPER = Bukkit.getVersion().contains("git-Paper");
private static final boolean paper = Bukkit.getVersion().contains("git-Paper");
public static boolean isPaper(){
return paper;
}
public FightWorld() {
super(ArenaMode.Restartable.contains(Config.mode) || Config.replayserver(), FightState.Schem);
@ -56,7 +57,7 @@ public class FightWorld extends StateDependent {
@Override
public void disable() {
Bukkit.getScheduler().runTask(FightSystem.getPlugin(), FightWorld::resetWorld); //Delay to prevent raceconditions with techhider and hullhider
resetWorld();
}
public static void forceLoad(){

Datei anzeigen

@ -51,7 +51,7 @@ public class HotbarKit extends Kit {
public static final HotbarKit SPECTATOR_KIT = new HotbarKit();
static {
for(int i = 0; i < 9; i++)
SPECTATOR_KIT.setItem(i, "JOIN_REQUEST", new ItemBuilder(Material.PAPER).build(), GUI::joinRequest);
SPECTATOR_KIT.setItem(i, "JOIN_REQUEST", new ItemBuilder(Material.PAPER).removeAllAttributes().build(), GUI::joinRequest);
}
private static final int HOTBAR_SIZE = 9;

Datei anzeigen

@ -30,7 +30,6 @@ import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWItem;
import de.steamwar.sql.PersonalKit;
import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
@ -70,19 +69,11 @@ public class Kit {
}
}
@Getter
private final String name;
@Getter
private final ItemStack[] inventory;
@Getter
private final ItemStack[] armor;
@Getter
private final Collection<PotionEffect> effects;
/* In which stage is entern allowed? */
@Getter
private final int enterStage;
/* Is this kit allowed to set/handle tnt? */
@Getter
private final boolean tnt;
private final boolean leaderAllowed;
private final boolean memberAllowed;
@ -149,6 +140,10 @@ public class Kit {
return kits;
}
public String getName() {
return name;
}
public boolean canUseKit(boolean leader){
if (leader) {
return leaderAllowed;
@ -161,6 +156,10 @@ public class Kit {
return !memberAllowed;
}
public ItemStack[] getInventory() {
return inventory;
}
public boolean contains(ItemStack stack) {
for(ItemStack i : inventory) {
if(similar(i, stack))
@ -173,6 +172,24 @@ public class Kit {
return false;
}
public ItemStack[] getArmor() {
return armor;
}
public Collection<PotionEffect> getEffects() {
return effects;
}
/* Is this kit allowed to set/handle tnt? */
public boolean isTnt(){
return tnt;
}
/* In which stage is entern allowed? */
public int getEnterStage() {
return enterStage;
}
public void toPersonalKit(PersonalKit kit) {
kit.setContainer(inventory, armor);
}

Datei anzeigen

@ -21,72 +21,52 @@ package de.steamwar.fightsystem.listener;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.events.TeamDeathEvent;
import de.steamwar.fightsystem.events.TeamLeaveEvent;
import de.steamwar.fightsystem.events.TeamSpawnEvent;
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.StateDependentListener;
import de.steamwar.fightsystem.states.StateDependentTask;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class ArenaBorder implements Listener {
private final Border spectatorBorder = new Border(Config.PlayerRegion, true, 5, "NO_ARENA_LEAVING", "ArenaBorder.spectatorBorder");
private final Border playerBorder = new Border(Config.PlayerRegion.to2d(), true, 5, "NO_ARENA_LEAVING", "ArenaBorder.playerBorder");
public ArenaBorder() {
new StateDependentListener(ArenaMode.All, FightState.All, this);
new StateDependentTask(ArenaMode.All, FightState.Running, this::damage, 2, 2);
new StateDependentListener(!Config.GroundWalkable, FightState.AntiRunning, new Listener() {
@EventHandler
public void onMove(PlayerMoveEvent e) {
Player player = e.getPlayer();
if(e.getTo().getY() <= Config.PlayerRegion.getMinY() && playerBorder.contains(player))
player.teleport(Fight.getPlayerTeam(player).getSpawn());
}
});
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
addToSpectator(e.getPlayer());
}
public void arenaBorder(PlayerMoveEvent event){
Player player = event.getPlayer();
FightTeam team = Fight.getPlayerTeam(player);
@EventHandler
public void onTeamJoin(TeamSpawnEvent e) {
e.getFightPlayer().ifPlayer(player -> {
spectatorBorder.removePlayer(player);
playerBorder.addPlayer(player);
});
}
if(Config.ArenaLeaveable && team == null)
return;
@EventHandler
public void onTeamDeath(TeamDeathEvent e) {
e.getFightPlayer().ifPlayer(player -> {
playerBorder.removePlayer(player);
addToSpectator(player);
});
}
Location to = event.getTo();
assert to != null;
@EventHandler
public void onTeamLeave(TeamLeaveEvent e) {
e.getFightPlayer().ifPlayer(player -> {
playerBorder.removePlayer(player);
addToSpectator(player);
});
}
if(Config.PlayerRegion.inRegion(to))
return;
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
spectatorBorder.removePlayer(e.getPlayer());
if(to.getY() <= Config.PlayerRegion.getMinY() && player.getGameMode() != GameMode.SPECTATOR && team != null) {
if(!Config.GroundWalkable && !FightState.infight())
player.teleport(team.getSpawn());
return;
}
player.teleport(event.getFrom());
FightSystem.getMessage().sendPrefixless("NO_ARENA_LEAVING", player, ChatMessageType.ACTION_BAR);
}
private void damage() {
@ -98,11 +78,4 @@ public class ArenaBorder implements Listener {
}
});
}
private void addToSpectator(Player player) {
if(Config.ArenaLeaveable || !player.isOnline() || playerBorder.contains(player))
return;
spectatorBorder.addPlayer(player);
}
}

Datei anzeigen

@ -0,0 +1,32 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.listener;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.fightsystem.utils.BountifulWrapper;
public class ArrowPickup {
public ArrowPickup() {
new StateDependentListener(ArenaMode.All, FightState.All, BountifulWrapper.impl.newDenyArrowPickupListener());
}
}

Datei anzeigen

@ -85,7 +85,7 @@ public class ArrowStopper {
}
private boolean checkBlock(Block block) {
return Config.HiddenBlocks.contains(block.getType());
return Config.HiddenBlocks.contains(block.getType().name().toLowerCase());
}
private boolean invalidEntity(Projectile entity) {

Datei anzeigen

@ -1,148 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.listener;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentTask;
import de.steamwar.fightsystem.utils.FlatteningWrapper;
import de.steamwar.fightsystem.utils.Region;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import java.util.*;
import java.util.logging.Level;
public class Border {
private final Map<UUID, Set<Block>> ghostBarriers = new HashMap<>();
private final Map<UUID, Location> lastLocation = new HashMap<>();
private final boolean contain;
private final String resetMessage;
private final String name;
private final Region region;
private final int ghostRange;
private final int ghostSize;
public Border(Region region, boolean contain, int ghostRange, String resetMessage, String name) {
this.contain = contain;
this.resetMessage = resetMessage;
this.name = name;
this.region = region;
this.ghostRange = ghostRange;
this.ghostSize = 2*ghostRange + 1;
new StateDependentTask(ArenaMode.All, FightState.All, this::run, 1, 1);
}
public void addPlayer(Player player) {
if(ghostBarriers.containsKey(player.getUniqueId()))
return;
ghostBarriers.put(player.getUniqueId(), new HashSet<>());
lastLocation.put(player.getUniqueId(), player.getLocation());
FightSystem.getPlugin().getLogger().log(Level.INFO, () -> player.getName() + " was added to border " + name);
}
public boolean contains(Player player) {
return ghostBarriers.containsKey(player.getUniqueId());
}
public void removePlayer(Player player) {
FightSystem.getPlugin().getLogger().log(Level.INFO, () -> player.getName() + " was removed from border " + name);
lastLocation.remove(player.getUniqueId());
Set<Block> blocks = ghostBarriers.remove(player.getUniqueId());
if(blocks == null || !player.isOnline())
return;
for(Block block : blocks)
sendChange(player, block, Material.AIR);
}
private void run() {
List<UUID> offline = new ArrayList<>();
for(Map.Entry<UUID, Set<Block>> entry : ghostBarriers.entrySet()) {
UUID uuid = entry.getKey();
Player player = Bukkit.getPlayer(uuid);
if(player == null) {
offline.add(uuid);
continue;
}
Location location = player.getLocation();
if(region.playerInRegion(location) != contain) {
player.teleport(lastLocation.get(uuid));
FightSystem.getMessage().sendPrefixless(resetMessage, player, ChatMessageType.ACTION_BAR);
return;
}
Set<Block> ghostBlocks = entry.getValue();
Region ghostRegion = Region.fromSize(location.getBlockX() - ghostRange, location.getBlockY() - ghostRange, location.getBlockZ() - ghostRange, ghostSize, ghostSize, ghostSize);
ghostBlocks.removeIf(block -> {
if(!ghostRegion.inRegion(block)) {
sendChange(player, block, Material.AIR);
return true;
}
return false;
});
if(contain) {
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX()-1, region.getMinY(), region.getMinZ(), 1, region.getSizeY(), region.getSizeZ()).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX(), region.getMinY()-1, region.getMinZ(), region.getSizeX(), 1, region.getSizeZ()).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX(), region.getMinY(), region.getMinZ()-1, region.getSizeX(), region.getSizeY(), 1).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMaxX(), region.getMinY(), region.getMinZ(), 1, region.getSizeY(), region.getSizeZ()).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX(), region.getMaxY(), region.getMinZ(), region.getSizeX(), 1, region.getSizeZ()).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX(), region.getMinY(), region.getMaxZ(), region.getSizeX(), region.getSizeY(), 1).intersection(ghostRegion));
} else {
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX(), region.getMinY(), region.getMinZ(), 1, region.getSizeY(), region.getSizeZ()).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX(), region.getMinY(), region.getMinZ(), region.getSizeX(), 1, region.getSizeZ()).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX(), region.getMinY(), region.getMinZ(), region.getSizeX(), region.getSizeY(), 1).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMaxX()-1, region.getMinY(), region.getMinZ(), 1, region.getSizeY(), region.getSizeZ()).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX(), region.getMaxY()-1, region.getMinZ(), region.getSizeX(), 1, region.getSizeZ()).intersection(ghostRegion));
borderIteration(player, ghostBlocks, Region.fromSize(region.getMinX(), region.getMinY(), region.getMaxZ()-1, region.getSizeX(), region.getSizeY(), 1).intersection(ghostRegion));
}
lastLocation.put(entry.getKey(), location);
}
offline.forEach(uuid -> FightSystem.getPlugin().getLogger().log(Level.INFO, () -> uuid + " was removed from border " + name));
offline.forEach(ghostBarriers::remove);
offline.forEach(lastLocation::remove);
}
private void borderIteration(Player player, Set<Block> ghostBlocks, Region border) {
border.forEach((x, y, z) -> {
Block block = Config.world.getBlockAt(x, y, z);
if(ghostBlocks.add(block))
sendChange(player, block, Material.BARRIER);
});
}
private void sendChange(Player player, Block block, Material type) {
if(block.getType() == Material.AIR)
FlatteningWrapper.impl.sendBlockChange(player, block, type);
}
}

Datei anzeigen

@ -40,7 +40,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
@ -154,6 +153,14 @@ public class Permanent implements Listener {
e.setCancelled(true);
}
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent e) {
Block block = e.getBlock();
for(ItemStack stack : block.getDrops(e.getPlayer().getItemInHand()))
Config.world.dropItemNaturally(block.getLocation(), stack);
}
@EventHandler
public void onDropPickup(PlayerPickupItemEvent e) {
if(!(Config.ArenaRegion.inRegion(e.getItem().getLocation())))
@ -219,25 +226,4 @@ public class Permanent implements Listener {
if(e.getItem().getType() == Material.TNT || FlatteningWrapper.impl.isFacingWater(block))
e.setCancelled(true);
}
@EventHandler
public void blockPlace(BlockPlaceEvent event) {
Player player = event.getPlayer();
Block block = event.getBlock();
if(Fight.teams().stream().anyMatch(team -> team.getExtendRegion().inRegion(block)))
return;
event.setCancelled(true);
FightSystem.getMessage().sendPrefixless("NO_BLOCK_PLACE", player, ChatMessageType.ACTION_BAR);
}
@EventHandler
public void blockBreak(BlockBreakEvent event) {
Block block = event.getBlock();
if(Config.BlueExtendRegion.getMinY() <= block.getY())
return;
event.setCancelled(true);
FightSystem.getMessage().sendPrefixless("NO_BLOCK_BREAK", event.getPlayer(), ChatMessageType.ACTION_BAR);
}
}

Datei anzeigen

@ -23,9 +23,6 @@ import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.events.TeamDeathEvent;
import de.steamwar.fightsystem.events.TeamLeaveEvent;
import de.steamwar.fightsystem.events.TeamSpawnEvent;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightPlayer;
import de.steamwar.fightsystem.fight.FightTeam;
@ -145,11 +142,6 @@ public class Recording implements Listener {
return packet;
}
@EventHandler
public void onPlayerSpawn(TeamSpawnEvent e) {
GlobalRecorder.getInstance().playerJoins(e.getFightPlayer().getEntity(), e.getFightPlayer().getUser());
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerMove(PlayerMoveEvent e){
if(isNotSent(e.getPlayer()))
@ -159,13 +151,19 @@ public class Recording implements Listener {
}
@EventHandler
public void onPlayerDeath(TeamDeathEvent e) {
GlobalRecorder.getInstance().entityDespawns(e.getFightPlayer().getEntity());
public void onPlayerDeath(PlayerDeathEvent e) {
if(isNotSent(e.getEntity()))
return;
GlobalRecorder.getInstance().entityDespawns(e.getEntity());
}
@EventHandler
public void onPlayerLeave(TeamLeaveEvent e) {
GlobalRecorder.getInstance().entityDespawns(e.getFightPlayer().getEntity());
public void onPlayerQuit(PlayerQuitEvent e){
if(isNotSent(e.getPlayer()))
return;
GlobalRecorder.getInstance().entityDespawns(e.getPlayer());
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)

Datei anzeigen

@ -22,122 +22,109 @@ package de.steamwar.fightsystem.listener;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.events.BoardingEvent;
import de.steamwar.fightsystem.events.TeamDeathEvent;
import de.steamwar.fightsystem.events.TeamLeaveEvent;
import de.steamwar.fightsystem.events.TeamSpawnEvent;
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 de.steamwar.fightsystem.states.StateDependentTask;
import de.steamwar.fightsystem.utils.Region;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
public class TeamArea implements Listener {
private final FightTeam team;
private final Border spectatorBorder;
private final Border bordingBorder;
private final Set<Player> realSpectator = new HashSet<>();
public TeamArea(FightTeam team) {
this.team = team;
this.spectatorBorder = new Border(team.getExtendRegion(), false, 5, "NO_TEAMAREA", team.getName() + ".spectatorBorder");
this.bordingBorder = new Border(team.getExtendRegion().to2d(), true, 1, "NO_ENTERN", team.getName() + ".boardingBorder");
private static final Set<Player> realSpectator = new HashSet<>();
public TeamArea() {
new StateDependentListener(ArenaMode.AntiTest, FightState.All, this);
new StateDependentTask(ArenaMode.AntiTest, FightState.TeamFix, this::realSpectatorCheck, 1, 1);
new OneShotStateDependent(ArenaMode.AntiTest, FightState.Spectate, () -> Fight.teams().forEach(t -> t.getPlayers().forEach(this::teamSpectator)));
}
@EventHandler
public void playerJoin(PlayerJoinEvent e) {
Player player = e.getPlayer();
if(Fight.getPlayerTeam(player) != team && !Config.isReferee(player))
spectatorBorder.addPlayer(player);
}
public void teamAreas(PlayerMoveEvent event) {
Player player = event.getPlayer();
if(Config.isReferee(player))
return;
@EventHandler
public void teamJoin(TeamSpawnEvent e) {
FightPlayer fightPlayer = e.getFightPlayer();
if(fightPlayer.getTeam() == team) {
fightPlayer.ifPlayer(player -> {
spectatorBorder.removePlayer(player);
bordingBorder.addPlayer(player);
});
}
}
@EventHandler
public void teamLeave(TeamLeaveEvent e) {
FightPlayer fightPlayer = e.getFightPlayer();
fightPlayer.ifPlayer(spectatorBorder::addPlayer);
if(fightPlayer.getTeam() == team)
fightPlayer.ifPlayer(bordingBorder::removePlayer);
}
@EventHandler
public void boarding(BoardingEvent e) {
FightPlayer fightPlayer = e.getFightPlayer();
if(fightPlayer.getTeam() == team) {
fightPlayer.ifPlayer(bordingBorder::removePlayer);
} else {
fightPlayer.ifPlayer(spectatorBorder::removePlayer);
}
}
@EventHandler
public void teamDeath(TeamDeathEvent e) {
teamSpectator(e.getFightPlayer());
}
private void teamSpectator(FightPlayer fightPlayer) {
if(fightPlayer.getTeam() == team) {
fightPlayer.ifPlayer(bordingBorder::removePlayer);
} else {
fightPlayer.ifPlayer(spectatorBorder::addPlayer);
}
FightTeam team = Fight.getPlayerTeam(player);
Fight.teams().forEach(t -> checkInTeamRegion(event, t, player, team));
}
@EventHandler
public void playerQuit(PlayerQuitEvent e) {
Player player = e.getPlayer();
spectatorBorder.removePlayer(player);
bordingBorder.removePlayer(player);
realSpectator.remove(player);
realSpectator.remove(e.getPlayer());
}
private void realSpectatorCheck() {
for(FightPlayer fightPlayer : team.getPlayers()) {
if(fightPlayer.isLiving())
continue;
@EventHandler
public void blockPlace(BlockPlaceEvent event) {
Player player = event.getPlayer();
Block block = event.getBlock();
if(Config.BlueExtendRegion.inRegion(block) || Config.RedExtendRegion.inRegion(block))
return;
fightPlayer.ifPlayer(player -> {
boolean inRegion = team.getExtendRegion().playerInRegion(player.getLocation());
if(inRegion && !realSpectator.contains(player)) {
realSpectator.add(player);
event.setCancelled(true);
FightSystem.getMessage().sendPrefixless("NO_BLOCK_PLACE", player, ChatMessageType.ACTION_BAR);
}
//Later to prevent race condition with Fight.setSpecatator() during respawn
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> {
if(!player.isOnline())
return;
Fight.pseudoSpectator(player, false);
}, 2);
}else if(!inRegion && realSpectator.contains(player)) {
Fight.pseudoSpectator(player, true);
realSpectator.remove(player);
}
});
@EventHandler
public void blockBreak(BlockBreakEvent event) {
Block block = event.getBlock();
if(Config.BlueExtendRegion.getMinY() <= block.getY())
return;
event.setCancelled(true);
FightSystem.getMessage().sendPrefixless("NO_BLOCK_BREAK", event.getPlayer(), ChatMessageType.ACTION_BAR);
}
private void checkInTeamRegion(PlayerMoveEvent event, FightTeam team, Player player, FightTeam playerTeam) {
boolean spectator = player.getGameMode() == GameMode.SPECTATOR;
if(!spectator && playerTeam != null && playerTeam.canPlayerEntern(player))
return; // Player can entern
Region region = team.getExtendRegion();
boolean inRegion = region.in2dRegion(event.getTo());
if(team == playerTeam) {
if(spectator) {
realSpectator(inRegion, player);
} else if (!playerTeam.canPlayerEntern(player) && !inRegion) {
reset(event, "NO_ENTERN"); // Leaving prior to entern
}
return; // Always allowed in own region
}
if(region.playerInRegion(event.getTo())) {
reset(event, "NO_TEAMAREA"); // Not allowed in region
if(team.getSchemRegion().playerInRegion(event.getTo()) && Config.PreperationArea >= 5){ // Preventing false positives due to small extension
player.kickPlayer(null);
Bukkit.getLogger().log(Level.INFO, player.getName() + " has entered a team area");
}
}
}
private void realSpectator(boolean inRegion, Player player) {
if(inRegion && !realSpectator.contains(player)) {
Fight.pseudoSpectator(player, false);
realSpectator.add(player);
}else if(!inRegion && realSpectator.contains(player)) {
Fight.pseudoSpectator(player, true);
realSpectator.remove(player);
}
}
private void reset(PlayerMoveEvent event, String message){
Player player = event.getPlayer();
player.teleport(event.getFrom());
FightSystem.getMessage().sendPrefixless(message, player, ChatMessageType.ACTION_BAR);
}
}

Datei anzeigen

@ -71,27 +71,19 @@ public class WaterRemover implements Listener {
event.setYield(0); //No drops (additionally to world config)
FightTeam spawn = tnt.remove(event.getEntity().getEntityId());
if(spawn != null && !spawn.getExtendRegion().inRegion(event.getLocation())) {
Block b = event.getLocation().getBlock();
for(int y = -1; y <= 1; y++) {
for(int z = -1; z <= 1; z++) {
for(int x = -1; x <= 1; x++) {
checkBlock(b.getRelative(x, y, z));
}
}
}
if(spawn != null && event.blockList().isEmpty() && Fight.getOpposite(spawn).getExtendRegion().inRegion(event.getLocation())) {
checkBlock(event.getLocation().getBlock());
}
event.blockList().forEach(this::checkNeighbours);
}
for(Block b : event.blockList()){
//b cannot be water or air due to current explosion
private void checkNeighbours(Block b) {
checkBlock(b.getRelative(BlockFace.UP));
checkBlock(b.getRelative(BlockFace.EAST));
checkBlock(b.getRelative(BlockFace.WEST));
checkBlock(b.getRelative(BlockFace.NORTH));
checkBlock(b.getRelative(BlockFace.SOUTH));
checkBlock(b.getRelative(BlockFace.DOWN));
checkBlock(b.getRelative(BlockFace.UP));
checkBlock(b.getRelative(BlockFace.EAST));
checkBlock(b.getRelative(BlockFace.WEST));
checkBlock(b.getRelative(BlockFace.NORTH));
checkBlock(b.getRelative(BlockFace.SOUTH));
}
}
private void checkBlock(Block b) {
@ -106,6 +98,10 @@ public class WaterRemover implements Listener {
if(b.getY() < MIN_Y)
return;
checkNeighbours(b);
checkBlock(b.getRelative(BlockFace.UP));
checkBlock(b.getRelative(BlockFace.EAST));
checkBlock(b.getRelative(BlockFace.WEST));
checkBlock(b.getRelative(BlockFace.NORTH));
checkBlock(b.getRelative(BlockFace.SOUTH));
}
}

Datei anzeigen

@ -22,17 +22,19 @@ package de.steamwar.fightsystem.record;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependent;
import lombok.Getter;
import java.io.*;
import java.util.zip.GZIPOutputStream;
public class FileRecorder extends StateDependent implements Recorder {
@Getter
private static final File file = new File(Config.world.getWorldFolder(), "recording.recording");
private DataOutputStream outputStream;
public static File getFile() {
return file;
}
public FileRecorder(){
super(Config.ReplayID == 0, FightState.Recording);
register();

Datei anzeigen

@ -41,7 +41,7 @@ public class LiveRecorder extends StateDependent implements Recorder {
@Override
public void enable() {
try {
socket = new Socket(Config.spectateIP, Config.SpectatePort);
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 disable
socket.setTcpNoDelay(true); // Don't wait on ack

Datei anzeigen

@ -33,7 +33,7 @@ public class LiveServer {
private final ServerSocket socket;
public LiveServer() throws IOException {
socket = new ServerSocket(Config.SpectatePort);
socket = new ServerSocket(Config.spectatePort);
Bukkit.getScheduler().runTaskAsynchronously(FightSystem.getPlugin(), this::acceptConnections);
}

Datei anzeigen

@ -88,8 +88,8 @@ public class PacketProcessor implements Listener {
private final PacketSource source;
private final BukkitTask task;
private final LinkedList<Runnable> syncList = new LinkedList<>();
private final Set<Integer> hiddenBlockIds = Config.HiddenBlocks.stream().flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet());
private final int obfuscateWith = BlockIds.impl.materialToId(Config.ObfuscateWith);
private final Set<Integer> hiddenBlockIds = Config.HiddenBlocks.stream().map(String::toUpperCase).map(Material::getMaterial).flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet());
private final int obfuscateWith = BlockIds.impl.materialToId(Material.getMaterial(Config.ObfuscateWith.toUpperCase()));
private final FreezeWorld freezer = new FreezeWorld();
private final REntityServer entityServer = new REntityServer();
private final Map<Integer, REntity> entities = new HashMap<>();
@ -165,11 +165,6 @@ public class PacketProcessor implements Listener {
entityServer.addPlayer(player);
}
private void addREntity(int entityId, REntity entity) {
entities.put(entityId, entity);
FightSystem.getHullHider().updateREntity(entity);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerJoin(PlayerJoinEvent e) {
entityServer.addPlayer(e.getPlayer());
@ -240,7 +235,7 @@ public class PacketProcessor implements Listener {
execSync(() -> {
SteamwarUser user = SteamwarUser.get(userId);
addREntity(entityId, new RPlayer(entityServer, user.getUUID(), user.getUserName(), Config.SpecSpawn));
entities.put(entityId, new RPlayer(entityServer, user.getUUID(), user.getUserName(), Config.SpecSpawn));
team.addEntry(user.getUserName());
});
}
@ -262,10 +257,8 @@ public class PacketProcessor implements Listener {
execSync(() -> {
REntity entity = entities.get(entityId);
if(entity != null) {
if(entity != null)
entity.move(locX, locY, locZ, pitch, yaw, headYaw);
FightSystem.getHullHider().updateREntity(entity);
}
});
}
@ -274,10 +267,8 @@ public class PacketProcessor implements Listener {
execSync(() -> {
REntity entity = entities.remove(entityId);
if(entity != null) {
FightSystem.getHullHider().despawnREntity(entity);
if(entity != null)
entity.die();
}
});
}
@ -298,7 +289,7 @@ public class PacketProcessor implements Listener {
private void tntSpawn() throws IOException {
int entityId = source.readInt();
execSync(() -> addREntity(entityId, new REntity(entityServer, EntityType.PRIMED_TNT, Config.SpecSpawn)));
execSync(() -> entities.put(entityId, new REntity(entityServer, EntityType.PRIMED_TNT, Config.SpecSpawn)));
}
private void entityVelocity() throws IOException {
@ -353,13 +344,13 @@ public class PacketProcessor implements Listener {
private void arrowSpawn() throws IOException {
int entityId = source.readInt();
execSync(() -> addREntity(entityId, new REntity(entityServer, EntityType.ARROW, Config.SpecSpawn)));
execSync(() -> entities.put(entityId, new REntity(entityServer, EntityType.ARROW, Config.SpecSpawn)));
}
private void fireballSpawn() throws IOException {
int entityId = source.readInt();
execSync(() -> addREntity(entityId, new REntity(entityServer, EntityType.FIREBALL, Config.SpecSpawn)));
execSync(() -> entities.put(entityId, new REntity(entityServer, EntityType.FIREBALL, Config.SpecSpawn)));
}
private void send(ChatMessageType type) throws IOException {
@ -446,10 +437,7 @@ public class PacketProcessor implements Listener {
if(!Config.ArenaRegion.in2dRegion(x, z))
return; //Outside of the arena
execSync(() -> {
BlockIdWrapper.impl.setBlock(Config.world, x, y, z, TechHiderWrapper.ENABLED && hiddenBlockIds.contains(blockState) ? obfuscateWith : blockState);
FightSystem.getHullHider().blockUpdate(Config.world.getBlockAt(x, y, z), BlockIdWrapper.impl.idToMaterial(blockState));
});
execSync(() -> BlockIdWrapper.impl.setBlock(Config.world, x, y, z, TechHiderWrapper.ENABLED && hiddenBlockIds.contains(blockState) ? obfuscateWith : blockState));
}
private void particle() throws IOException {
@ -590,7 +578,6 @@ public class PacketProcessor implements Listener {
private void endReplay() {
HandlerList.unregisterAll(this);
entityServer.close();
entities.values().forEach(FightSystem.getHullHider()::despawnREntity);
entities.clear();
freezer.disable();

Datei anzeigen

@ -19,8 +19,6 @@
package de.steamwar.fightsystem.states;
import lombok.Getter;
import java.util.*;
public enum FightState {
@ -50,9 +48,12 @@ public enum FightState {
public static final Set<FightState> AntiSpectate = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(SPECTATE)));
private static final Map<IStateDependent, Boolean> stateDependentFeatures = new HashMap<>();
@Getter
private static FightState fightState = PRE_LEADER_SETUP;
public static FightState getFightState() {
return fightState;
}
public static void registerStateDependent(IStateDependent stateDependent){
if(stateDependent.enabled().isEmpty())
return;

Datei anzeigen

@ -19,28 +19,14 @@
package de.steamwar.fightsystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.core.VersionDependent;
import de.steamwar.fightsystem.FightSystem;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
public interface BlockIdWrapper {
Class<?> worldServer = Reflection.getClass("{nms.server.level}.WorldServer");
Reflection.MethodInvoker getWorldHandle = Reflection.getTypedMethod(Reflection.getClass("{obc}.CraftWorld"), "getHandle", worldServer);
Class<?> craftPlayer = Reflection.getClass("{obc}.entity.CraftPlayer");
Class<?> entityPlayer = Reflection.getClass("{nms.server.level}.EntityPlayer");
Reflection.MethodInvoker getPlayer = Reflection.getTypedMethod(craftPlayer, "getHandle", entityPlayer);
BlockIdWrapper impl = VersionDependent.getVersionImpl(FightSystem.getPlugin());
Material idToMaterial(int blockState);
int blockToId(Block block);
void setBlock(World world, int x, int y, int z, int blockState);
void trackEntity(Player player, int entity);
void untrackEntity(Player player, int entity);
}

Datei anzeigen

@ -51,7 +51,7 @@ public class EnterHandler implements IStateDependent {
private void registerTeam(FightTeam team){
for(FightPlayer fp : team.getPlayers()){
fp.startEnternCountdown(null);
fp.startEnternCountdown();
}
}

Datei anzeigen

@ -35,7 +35,6 @@ import de.steamwar.network.packets.common.FightEndsPacket;
import de.steamwar.sql.Replay;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import org.bukkit.Bukkit;
import java.sql.Timestamp;
@ -47,7 +46,6 @@ import static de.steamwar.sql.Fight.create;
public class FightStatistics {
@Getter
private static boolean unranked = false;
public static void unrank() {
@ -55,6 +53,10 @@ public class FightStatistics {
FightUI.addSubtitle("UI_UNRANKED");
}
public static boolean isUnranked() {
return unranked;
}
private Timestamp starttime = Timestamp.from(Instant.now());
public FightStatistics() {
@ -96,12 +98,12 @@ public class FightStatistics {
Integer redSchem;
try {
blueSchem = SchematicNode.getSchematicNode(Fight.getBlueTeam().getSchematic()).getId();
} catch (NullPointerException e) {
} catch (SecurityException e) {
blueSchem = null;
}
try {
redSchem = SchematicNode.getSchematicNode(Fight.getRedTeam().getSchematic()).getId();
} catch (NullPointerException e) {
} catch (SecurityException e) {
redSchem = null;
}

Datei anzeigen

@ -31,7 +31,6 @@ import de.steamwar.fightsystem.states.OneShotStateDependent;
import de.steamwar.fightsystem.states.StateDependentCountdown;
import de.steamwar.fightsystem.states.StateDependentTask;
import de.steamwar.fightsystem.winconditions.Wincondition;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -44,8 +43,10 @@ import java.util.stream.Collectors;
public class FightUI {
@Getter
private static FightUI instance;
public static FightUI getInstance() {
return instance;
}
public FightUI() {
new StateDependentTask(ArenaMode.AntiReplay, FightState.All, this::update, 20, 20);

Datei anzeigen

@ -22,7 +22,6 @@ package de.steamwar.fightsystem.utils;
import de.steamwar.core.VersionDependent;
import de.steamwar.fightsystem.FightSystem;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
@ -50,5 +49,4 @@ public interface FlatteningWrapper {
boolean isFacingWater(Block dispenser);
boolean isCrouching(Player player);
void sendBlockChange(Player player, Block block, Material type);
}

Datei anzeigen

@ -1,379 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.utils;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.entity.REntity;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.FightTeam;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.logging.Level;
public class Hull {
private static boolean isOccluding(Material material) {
return material.isOccluding() || Config.HiddenBlocks.contains(material);
}
private final Region region;
private final boolean groundVisible;
private final BitSet occluding;
private final BitSet visibility;
private final Map<IntVector, Map<IntVector, BitSet>> blockVisibility = new HashMap<>();
private final Set<IntVector> uncoveredSurface = new HashSet<>();
private final HashSet<Player> players = new HashSet<>();
private final Set<Entity> entities = new HashSet<>();
private final Set<REntity> rentities = new HashSet<>();
public Hull(FightTeam team) {
this.region = team.getSchemRegion();
this.groundVisible = region.getMinY() != Config.PlayerRegion.getMinY();
this.occluding = new BitSet(region.volume());
this.visibility = new BitSet(region.volume());
IntVector[] directions;
if (groundVisible) {
directions = new IntVector[]{
new IntVector(1, 0, 0),
new IntVector(-1, 0, 0),
new IntVector(0, 1, 0),
new IntVector(0, -1, 0),
new IntVector(0, 0, 1),
new IntVector(0, 0, -1)
};
} else {
directions = new IntVector[]{
new IntVector(1, 0, 0),
new IntVector(-1, 0, 0),
new IntVector(0, -1, 0),
new IntVector(0, 0, 1),
new IntVector(0, 0, -1)
};
}
// Generate quadrants for each direction
for (IntVector direction : directions) {
Map<IntVector, BitSet> map = new HashMap<>();
for (int z = (direction.z == 0 ? -1 : 0); z <= 1; z += 2) {
for (int y = (direction.y == 0 ? -1 : 0); y <= 1; y += 2) {
for (int x = (direction.x == 0 ? -1 : 0); x <= 1; x += 2) {
map.put(new IntVector(x, y, z), new BitSet(region.volume()));
}
}
}
blockVisibility.put(direction, map);
}
}
public boolean blockPrecise(Player player, int chunkX, int chunkY, int chunkZ) {
return players.contains(player) && !region.chunkSectionOutside(chunkX, chunkY, chunkZ);
}
public boolean isBlockHidden(Player player, int x, int y, int z) {
return region.inRegion(x, y, z) && players.contains(player) && !visibility.get(((y - region.getMinY()) * region.getSizeZ() + (z - region.getMinZ())) * region.getSizeX() + (x - region.getMinX()));
}
public boolean isLocationHidden(Player player, Location location) {
return players.contains(player) && region.inRegion(location) && !visibility.get(new IntVector(location).toId(region));
}
public void addPlayer(Player player) {
if(players.add(player)) {
for(Entity entity : entities)
BlockIdWrapper.impl.untrackEntity(player, entity.getEntityId());
}
}
public void removePlayer(Player player, boolean activeRemoval) {
if(players.remove(player) && activeRemoval) {
for(Entity entity : entities)
BlockIdWrapper.impl.trackEntity(player, entity.getEntityId());
// techhider triggers block change sending
}
}
public void checkEntity(Entity entity) {
Location location = entity.getLocation();
if(region.inRegion(location) && !visibility.get(new IntVector(location).toId(region))) { //TODO more precise
if(entities.add(entity)) {
for(Player player : players)
BlockIdWrapper.impl.untrackEntity(player, entity.getEntityId());
}
} else {
if(entities.remove(entity)) {
for(Player player : players)
BlockIdWrapper.impl.trackEntity(player, entity.getEntityId());
}
}
}
public void removeEntity(Entity entity) {
entities.remove(entity);
}
public void checkREntity(REntity entity) {
Location location = new Location(Config.world, entity.getX(), entity.getY(), entity.getZ());
if(region.inRegion(location) && !visibility.get(new IntVector(location).toId(region))) { //TODO more precise
if(rentities.add(entity))
entity.hide(true);
} else {
if(rentities.remove(entity))
entity.hide(false);
}
}
public void removeREntity(REntity entity) {
rentities.remove(entity);
}
public void initialize() {
visibility.clear();
occluding.clear();
uncoveredSurface.clear();
for (Map<IntVector, BitSet> direction : blockVisibility.values()) {
for (BitSet set : direction.values())
set.clear();
}
long start = System.currentTimeMillis();
region.forEach((x, y, z) -> {
IntVector block = new IntVector(x, y, z);
if (isOccluding(Config.world.getBlockAt(x, y, z).getType()))
occluding.set(block.toId(region));
});
forEachBorder((root, direction) -> {
for (Map.Entry<IntVector, BitSet> quadrant : blockVisibility.get(direction).entrySet()) {
checkBlock(new NullList<>(), root, direction, quadrant.getKey(), quadrant.getValue());
}
});
FightSystem.getPlugin().getLogger().log(Level.INFO, () -> "[HullHider] initialisation finished: " + (System.currentTimeMillis() - start) + " ms, visible blocks: " + visibility.cardinality());
}
public void updateBlockVisibility(Block b, Material changedType) {
IntVector root = new IntVector(b.getX(), b.getY(), b.getZ());
if (root.notInRegion(region))
return;
int id = root.toId(region);
if (!occluding.get(id) || isOccluding(changedType))
return;
List<IntVector> uncovered = new ArrayList<>();
occluding.clear(id);
for (Map.Entry<IntVector, Map<IntVector, BitSet>> direction : blockVisibility.entrySet()) {
for (Map.Entry<IntVector, BitSet> quadrant : direction.getValue().entrySet()) {
if (quadrant.getValue().get(id)) {
quadrant.getValue().clear(id);
checkBlock(uncovered, root, direction.getKey(), quadrant.getKey(), quadrant.getValue());
}
}
}
if(uncovered.isEmpty())
return;
Set<IntVector> uncoveredSet = new HashSet<>(uncovered);
Iterator<Entity> it = entities.iterator();
while(it.hasNext()) {
Entity entity = it.next();
if(uncoveredSet.contains(new IntVector(entity.getLocation()))) { //TODO more precise
it.remove();
for(Player player : players)
BlockIdWrapper.impl.trackEntity(player, entity.getEntityId());
}
}
Iterator<REntity> rit = rentities.iterator();
while(rit.hasNext()) {
REntity entity = rit.next();
if(uncoveredSet.contains(new IntVector(new Location(Config.world, entity.getX(), entity.getY(), entity.getZ())))) { //TODO more precise
rit.remove();
entity.hide(false);
}
}
uncoveredSurface.addAll(uncoveredSet);
uncoveredSurface.remove(root);
}
public void sendUncoveredBlocks() {
Map<IntVector, List<IntVector>> sectionWise = new HashMap<>();
for(IntVector uncovered : uncoveredSurface) {
sectionWise.computeIfAbsent(new IntVector(uncovered.x >> 4, uncovered.y >> 4, uncovered.z >> 4), section -> new ArrayList<>()).add(uncovered);
}
uncoveredSurface.clear();
for (Map.Entry<IntVector, List<IntVector>> entry : sectionWise.entrySet()) {
Object packet = HullHiderWrapper.impl.generateBlockChangePacket(entry.getValue());
if(packet == null)
continue;
players.forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
}
}
private void forEachBorder(BiConsumer<IntVector, IntVector> f) {
for (int x = region.getMinX(); x < region.getMaxX(); x++) {
for (int z = region.getMinZ(); z < region.getMaxZ(); z++) {
if (groundVisible)
f.accept(new IntVector(x, region.getMinY(), z), new IntVector(0, 1, 0));
f.accept(new IntVector(x, region.getMaxY() - 1, z), new IntVector(0, -1, 0));
}
}
for (int x = region.getMinX(); x < region.getMaxX(); x++) {
for (int y = region.getMinY(); y < region.getMaxY(); y++) {
f.accept(new IntVector(x, y, region.getMinZ()), new IntVector(0, 0, 1));
f.accept(new IntVector(x, y, region.getMaxZ() - 1), new IntVector(0, 0, -1));
}
}
for (int z = region.getMinZ(); z < region.getMaxZ(); z++) {
for (int y = region.getMinY(); y < region.getMaxY(); y++) {
f.accept(new IntVector(region.getMinX(), y, z), new IntVector(1, 0, 0));
f.accept(new IntVector(region.getMaxX() - 1, y, z), new IntVector(-1, 0, 0));
}
}
}
private void checkBlock(List<IntVector> uncovered, IntVector block, IntVector direction, IntVector quadrant, BitSet quadVisibility) {
if (block.notInRegion(region))
return;
int id = block.toId(region);
if (quadVisibility.get(id))
return;
quadVisibility.set(id);
if (!visibility.get(id)) {
visibility.set(id);
uncovered.add(block);
}
if (occluding.get(id))
return;
IntVector neighbour = block.add(direction);
checkBlock(uncovered, neighbour, direction, quadrant, quadVisibility);
boolean neigbourTransparent = boundedNonOccluding(neighbour);
boolean diagonalReachable = false;
if (direction.x == 0 && (neigbourTransparent || boundedNonOccluding(block.add(quadrant.x, 0, 0)))) {
checkBlock(uncovered, neighbour.add(quadrant.x, 0, 0), direction, quadrant, quadVisibility);
diagonalReachable = boundedNonOccluding(neighbour.add(quadrant.x, 0, 0));
}
if (direction.y == 0 && (neigbourTransparent || boundedNonOccluding(block.add(0, quadrant.y, 0)))) {
checkBlock(uncovered, neighbour.add(0, quadrant.y, 0), direction, quadrant, quadVisibility);
diagonalReachable = diagonalReachable || boundedNonOccluding(neighbour.add(0, quadrant.y, 0));
}
if (direction.z == 0 && (neigbourTransparent || boundedNonOccluding(block.add(0, 0, quadrant.z)))) {
checkBlock(uncovered, neighbour.add(0, 0, quadrant.z), direction, quadrant, quadVisibility);
diagonalReachable = diagonalReachable || boundedNonOccluding(neighbour.add(0, 0, quadrant.z));
}
if (diagonalReachable)
checkBlock(uncovered, neighbour.add(quadrant), direction, quadrant, quadVisibility);
}
private boolean boundedNonOccluding(IntVector block) {
return !(block.notInRegion(region) || occluding.get(block.toId(region)));
}
@Getter
@AllArgsConstructor
public static class IntVector {
private final int x;
private final int y;
private final int z;
public IntVector(Location location) {
this.x = location.getBlockX();
this.y = location.getBlockY();
this.z = location.getBlockZ();
}
public boolean notInRegion(Region region) {
return !region.inRegion(x, y, z);
}
public int toId(Region region) {
return ((y - region.getMinY()) * region.getSizeZ() + (z - region.getMinZ())) * region.getSizeX() + (x - region.getMinX());
}
public IntVector add(int x, int y, int z) {
return new IntVector(this.x + x, this.y + y, this.z + z);
}
public IntVector add(IntVector v) {
return add(v.x, v.y, v.z);
}
@Override
public int hashCode() {
return y << 24 ^ x << 12 ^ z;
}
@Override
public boolean equals(Object o) {
if(o == null || this.getClass() != o.getClass())
return false;
IntVector v = (IntVector) o;
return x == v.x && y == v.y && z == v.z;
}
@Override
public String toString() {
return x + "," + y + "," + z;
}
}
private static class NullList<E> extends AbstractList<E> {
@Override
public void add(int index, E element) {
// Straight to /dev/null!
}
@Override
public E get(int index) {
return null;
}
@Override
public int size() {
return 0;
}
}
}

Datei anzeigen

@ -1,241 +0,0 @@
/*
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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.core.Core;
import de.steamwar.entity.REntity;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightPlayer;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.listener.Recording;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependent;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.fightsystem.states.StateDependentTask;
import de.steamwar.techhider.TechHider;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
public class HullHider implements Listener {
private final Map<FightTeam, Hull> hullMap = new HashMap<>();
private final Hull[] hulls;
private final Map<Class<?>, BiFunction<Player, Object, Object>> packetHiders = new HashMap<>();
public HullHider() {
if(!TechHiderWrapper.ENABLED) {
hulls = new Hull[0];
return;
}
Fight.teams().forEach(team -> hullMap.put(team, new Hull(team)));
hulls = hullMap.values().toArray(new Hull[0]);
packetHiders.put(packetPlayOutWorldEvent, this::worldEventHider);
packetHiders.put(packetPlayOutExplosion, this::explosionHider);
posHiderGenerator("{nms.network.protocol.game}.PacketPlayOutWorldParticles", Core.getVersion() >= 18 ? double.class : float.class, 1.0);
posHiderGenerator("{nms.network.protocol.game}.PacketPlayOutNamedSoundEffect", int.class, 8.0);
if(Core.getVersion() >= 9 && Core.getVersion() < 18)
posHiderGenerator("{nms.network.protocol.game}.PacketPlayOutCustomSoundEffect", int.class, 8.0);
new StateDependentListener(TechHiderWrapper.ENABLED, FightState.Schem, this);
new StateDependent(TechHiderWrapper.ENABLED, FightState.Schem) {
@Override
public void enable() {
packetHiders.forEach(TinyProtocol.instance::addFilter);
Bukkit.getOnlinePlayers().forEach(HullHider.this::updatePlayer);
}
@Override
public void disable() {
Bukkit.getOnlinePlayers().forEach(player -> removePlayer(player, true));
packetHiders.forEach(TinyProtocol.instance::removeFilter);
}
}.register();
new StateDependentTask(TechHiderWrapper.ENABLED, FightState.Schem, this::onTick, 0, 1);
}
public void initialize(FightTeam team) {
if(!TechHiderWrapper.ENABLED)
return;
hullMap.get(team).initialize();
}
@EventHandler(priority = EventPriority.HIGH)
public void onJoin(PlayerJoinEvent e) {
updatePlayer(e.getPlayer());
}
@EventHandler
public void onLeave(PlayerQuitEvent e) {
removePlayer(e.getPlayer(), false);
}
public void updatePlayer(Player player) {
if(!TechHiderWrapper.ENABLED)
return;
FightTeam team = Fight.getPlayerTeam(player);
FightPlayer fp = Fight.getFightPlayer(player);
for(Map.Entry<FightTeam, Hull> hull : hullMap.entrySet()) {
if(Config.isReferee(player) || hull.getKey() == team || (fp != null && fp.canEntern())) {
hull.getValue().removePlayer(player, true);
} else {
hull.getValue().addPlayer(player);
}
}
}
private void removePlayer(Player player, boolean activeRemoval) {
for (Hull hull : hulls)
hull.removePlayer(player, activeRemoval);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPhysic(BlockPhysicsEvent e) {
if(FlatteningWrapper.impl.doRecord(e))
blockUpdate(e.getBlock(), e.getChangedType());
}
public void blockUpdate(Block block, Material changedType) {
for (Hull hull : hulls)
hull.updateBlockVisibility(block, changedType);
}
public boolean isBlockHidden(Player player, int x, int y, int z) {
if(!TechHiderWrapper.ENABLED)
return false;
for (Hull hull : hulls)
if(hull.isBlockHidden(player, x, y, z))
return true;
return false;
}
public boolean blockPrecise(Player player, int chunkX, int chunkY, int chunkZ) {
if(!TechHiderWrapper.ENABLED)
return false;
for (Hull hull : hulls)
if(hull.blockPrecise(player, chunkX, chunkY, chunkZ))
return true;
return false;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSpawn(EntitySpawnEvent e) {
for (Hull hull : hulls)
hull.checkEntity(e.getEntity());
}
private void onTick() {
Recording.iterateOverEntities(Objects::nonNull, entity -> {
for (Hull hull : hulls)
hull.checkEntity(entity);
});
for (Hull hull : hulls)
hull.sendUncoveredBlocks();
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onDeath(EntityDeathEvent e) {
for(Hull hull : hulls)
hull.removeEntity(e.getEntity());
}
public void updateREntity(REntity e) {
for(Hull hull : hulls)
hull.checkREntity(e);
}
public void despawnREntity(REntity e) {
for(Hull hull : hulls)
hull.removeREntity(e);
}
private static final Class<?> packetPlayOutWorldEvent = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutWorldEvent");
private static final Reflection.FieldAccessor<?> worldEventPosition = Reflection.getField(packetPlayOutWorldEvent, TechHider.blockPosition, 0);
public static final Reflection.FieldAccessor<Integer> blockPositionY = Reflection.getField("{nms.core}.BaseBlockPosition", int.class, 1);
private Object worldEventHider(Player player, Object packet) {
Object baseBlock = worldEventPosition.get(packet);
return packetHider(player, packet, new Location(Config.world, TechHider.blockPositionX.get(baseBlock), blockPositionY.get(baseBlock), TechHider.blockPositionZ.get(baseBlock)));
}
private static final Class<?> packetPlayOutExplosion = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutExplosion");
private static final Reflection.FieldAccessor<List> explosionBlocks = Reflection.getField(packetPlayOutExplosion, List.class, 0);
private static final Function<Object, Location> explosionLocation = posPacketToLocation(packetPlayOutExplosion, double.class, 1.0);
private Object explosionHider(Player player, Object packet) {
if(explosionBlocks.get(packet).isEmpty())
return packetHider(player, packet, explosionLocation.apply(packet));
return packet;
}
private void posHiderGenerator(String typeName, Class<? extends Number> posType, double factor) {
Class<?> type = Reflection.getClass(typeName);
Function<Object, Location> location = posPacketToLocation(type, posType, factor);
packetHiders.put(type, (player, packet) -> packetHider(player, packet, location.apply(packet)));
}
private static Function<Object, Location> posPacketToLocation(Class<?> type, Class<? extends Number> posType, double factor) {
Reflection.FieldAccessor<? extends Number> x = Reflection.getField(type, posType, 0);
Reflection.FieldAccessor<? extends Number> y = Reflection.getField(type, posType, 1);
Reflection.FieldAccessor<? extends Number> z = Reflection.getField(type, posType, 2);
return packet -> new Location(Config.world, x.get(packet).doubleValue()/factor, y.get(packet).doubleValue()/factor, z.get(packet).doubleValue()/factor);
}
private Object packetHider(Player player, Object packet, Location location) {
for(Hull hull : hulls) {
if(hull.isLocationHidden(player, location))
return null;
}
return packet;
}
}

Datei anzeigen

@ -1,31 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.utils;
import de.steamwar.core.VersionDependent;
import de.steamwar.fightsystem.FightSystem;
import java.util.List;
public interface HullHiderWrapper {
HullHiderWrapper impl = VersionDependent.getVersionImpl(FightSystem.getPlugin());
Object generateBlockChangePacket(List<Hull.IntVector> changes);
}

Datei anzeigen

@ -25,26 +25,51 @@ import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.List;
public class ItemBuilder {
private final ItemStack item;
private final ItemMeta meta;
public ItemBuilder(Material material) {
item = new ItemStack(material);
public ItemBuilder(Material matrial) {
item = new ItemStack(matrial);
meta = item.getItemMeta();
}
public ItemBuilder(Material matrial, int amount) {
item = new ItemStack(matrial, amount);
meta = item.getItemMeta();
meta.addItemFlags(ItemFlag.values());
}
@SuppressWarnings("deprecation")
public ItemBuilder(Material material, short subid) {
item = new ItemStack(material, 1, subid);
public ItemBuilder(Material matrial, short subid) {
item = new ItemStack(matrial, 1, subid);
meta = item.getItemMeta();
meta.addItemFlags(ItemFlag.values());
}
public ItemBuilder enchant() {
meta.addEnchant(Enchantment.DURABILITY, 1, true);
public ItemBuilder removeAllAttributes() {
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
meta.addItemFlags(ItemFlag.HIDE_DESTROYS);
meta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE);
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
meta.addItemFlags(ItemFlag.HIDE_PLACED_ON);
meta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
return this;
}
public ItemBuilder setDisplayName(String name) {
meta.setDisplayName(name);
return this;
}
public ItemBuilder addLore(List<String> lore) {
meta.setLore(lore);
return this;
}
public ItemBuilder addEnchantment(Enchantment enchantment, int level) {
meta.addEnchant(enchantment, level, true);
return this;
}
@ -52,4 +77,5 @@ public class ItemBuilder {
item.setItemMeta(meta);
return item;
}
}

Datei anzeigen

@ -19,11 +19,7 @@
package de.steamwar.fightsystem.utils;
import lombok.Getter;
@Getter
public class Message {
private final String msg;
private final Object[] params;
@ -31,4 +27,12 @@ public class Message {
this.msg = msg;
this.params = params;
}
public String getMsg() {
return msg;
}
public Object[] getParams() {
return params;
}
}

Datei anzeigen

@ -20,28 +20,13 @@
package de.steamwar.fightsystem.utils;
import de.steamwar.techhider.ProtocolUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.bukkit.Location;
import org.bukkit.block.Block;
import java.util.function.ObjIntConsumer;
@Getter
@AllArgsConstructor
public class Region {
public static final Region EMPTY = Region.fromSize(-10000, -10000, -10000, 0, 0, 0);
public static Region withExtension(int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ, int extendX, int extendY, int extendZ) {
return Region.fromSize(minX - extendX, minY - extendY, minZ - extendZ,
sizeX + extendX * 2, sizeY + extendY * 2, sizeZ + extendZ * 2);
}
public static Region fromSize(int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
return new Region(minX, minY, minZ, minX+sizeX, minY+sizeY, minZ+sizeZ);
}
private final int minX;
private final int minY;
private final int minZ;
@ -49,6 +34,44 @@ public class Region {
private final int maxY;
private final int maxZ;
public Region(int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ, int extendX, int extendY, int extendZ) {
this(minX - extendX, minY - extendY, minZ - extendZ,
sizeX + extendX * 2, sizeY + extendY * 2, sizeZ + extendZ * 2);
}
public Region(int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = minX + sizeX;
this.maxY = minY + sizeY;
this.maxZ = minZ + sizeZ;
}
public int getMinX() {
return minX;
}
public int getMinY() {
return minY;
}
public int getMinZ() {
return minZ;
}
public int getMaxX() {
return maxX;
}
public int getMaxY() {
return maxY;
}
public int getMaxZ() {
return maxZ;
}
public int getSizeX() {
return maxX - minX;
}
@ -82,12 +105,6 @@ public class Region {
getMinChunkZ() > cZ || cZ > getMaxChunkZ();
}
public boolean chunkSectionOutside(int cX, int cY, int cZ) {
return getMinChunkX() > cX || cX > getMaxChunkX() ||
ProtocolUtils.posToChunk(minY) > cY || cY > ProtocolUtils.posToChunk(maxY) ||
getMinChunkZ() > cZ || cZ > getMaxChunkZ();
}
public void forEachChunk(ObjIntConsumer<Integer> executor) {
for(int x = getMinChunkX(); x <= getMaxChunkX(); x++)
for(int z = getMinChunkZ(); z <= getMaxChunkZ(); z++)
@ -97,7 +114,7 @@ public class Region {
public void forEach(TriConsumer<Integer, Integer, Integer> executor) {
for(int x = minX; x < maxX; x++) {
for(int y = minY; y < maxY; y++) {
for (int z = minZ; z < maxZ; z++) {
for (int z = minZ; z <= maxZ; z++) {
executor.accept(x, y, z);
}
}
@ -125,7 +142,7 @@ public class Region {
}
public boolean playerInRegion(Location location){
return in2dRegion(location) && minY <= location.getY() && location.getY() < maxY;
return in2dRegion(location) && minY <= location.getY() && location.getY() + 1.8 < maxY;
}
public boolean in2dRegion(Block block){
@ -133,29 +150,13 @@ public class Region {
}
public boolean in2dRegion(int x, int z) {
return minX <= x && x < maxX && minZ <= z && z < maxZ;
return minX <= x && x < maxX && minZ <= z && z <= maxZ;
}
public boolean inRegion(Block block){
return in2dRegion(block) && minY <= block.getY() && block.getY() < maxY;
}
public boolean inRegion(int x, int y, int z) {
return in2dRegion(x, z) && minY <= y && y < maxY;
}
public Region intersection(Region other) {
int x = Math.max(minX, other.minX);
int y = Math.max(minY, other.minY);
int z = Math.max(minZ, other.minZ);
return new Region(x, y, z, Math.min(maxX, other.maxX), Math.min(maxY, other.maxY), Math.min(maxZ, other.maxZ));
}
public Region to2d() {
return new Region(minX, Integer.MIN_VALUE/2, minZ, maxX, Integer.MAX_VALUE/2, maxZ);
}
public interface TriConsumer<T, V, U>{
void accept(T x, V y, U z);
}

Datei anzeigen

@ -22,34 +22,30 @@ package de.steamwar.fightsystem.utils;
import de.steamwar.core.CraftbukkitWrapper;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.events.BoardingEvent;
import de.steamwar.fightsystem.events.TeamLeaveEvent;
import de.steamwar.fightsystem.events.TeamSpawnEvent;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependent;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.techhider.ProtocolUtils;
import de.steamwar.techhider.TechHider;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.concurrent.ConcurrentHashMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class TechHiderWrapper extends StateDependent implements TechHider.LocationEvaluator, Listener {
public class TechHiderWrapper extends StateDependent {
public static final boolean ENABLED = !Config.OnlyPublicSchematics && !Config.test() && Config.TechhiderActive;
private final ConcurrentHashMap<Player, Region> hiddenRegion = new ConcurrentHashMap<>();
private final TechHider techHider;
public TechHiderWrapper() {
super(ENABLED, FightState.Schem);
techHider = new TechHider(this, Config.ObfuscateWith, Config.HiddenBlocks, Config.HiddenBlockEntities);
new StateDependentListener(ENABLED, FightState.Schem, this);
techHider = new TechHider(this::bypass, Material.getMaterial(Config.ObfuscateWith), Config.HiddenBlocks.stream().map(String::toUpperCase).map(Material::getMaterial).collect(Collectors.toSet()), Config.HiddenBlockEntities);
register();
}
@ -61,82 +57,43 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati
@Override
public void disable() {
techHider.disable();
hiddenRegion.clear();
}
@EventHandler
public void teamJoin(TeamSpawnEvent e) {
e.getFightPlayer().ifPlayer(player -> hiddenRegion.put(player, getHiddenRegion(player)));
}
public List<ProtocolUtils.ChunkPos> prepareChunkReload(LivingEntity p, boolean hide) {
if(!ENABLED || !(p instanceof Player))
return Collections.emptyList();
@EventHandler
public void boarding(BoardingEvent e) {
e.getFightPlayer().ifPlayer(player -> hiddenRegion.put(player, getHiddenRegion(player)));
}
@EventHandler
public void teamLeave(TeamLeaveEvent e) {
e.getFightPlayer().ifPlayer(player -> {
if(player.isOnline())
hiddenRegion.put(player, getHiddenRegion(player));
List<ProtocolUtils.ChunkPos> chunksToReload = new ArrayList<>();
Config.ArenaRegion.forEachChunk((x, z) -> {
if(bypass((Player) p, x, z) == hide)
chunksToReload.add(new ProtocolUtils.ChunkPos(x, z));
});
return chunksToReload;
}
@EventHandler
public void playerQuit(PlayerQuitEvent e) {
Player player = e.getPlayer();
hiddenRegion.remove(player);
}
public void reloadChunks(Player player, Region region, Region exclusion) {
if(!ENABLED || !FightState.Schem.contains(FightState.getFightState()) || !player.isOnline())
public void reloadChunks(Player p, List<ProtocolUtils.ChunkPos> chunksToReload, boolean hide) {
if(!ENABLED || !FightState.Schem.contains(FightState.getFightState()))
return;
region.forEachChunk((chunkX, chunkZ) -> {
if(exclusion.chunkOutside(chunkX, chunkZ))
CraftbukkitWrapper.impl.sendChunk(player, chunkX, chunkZ);
});
}
@Override
public boolean skipChunk(Player player, int chunkX, int chunkZ) {
return getHiddenRegion(player).chunkOutside(chunkX, chunkZ);
}
@Override
public boolean skipChunkSection(Player player, int chunkX, int chunkY, int chunkZ) {
return getHiddenRegion(player).chunkSectionOutside(chunkX, chunkY, chunkZ);
}
@Override
public TechHider.State check(Player player, int x, int y, int z) {
if(hiddenRegion.computeIfAbsent(player, this::getHiddenRegion).inRegion(x, y, z)) {
if(FightSystem.getHullHider().isBlockHidden(player, x, y, z)) {
return TechHider.State.HIDE;
} else {
return TechHider.State.CHECK;
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> {
for(ProtocolUtils.ChunkPos chunk : chunksToReload){
if(bypass(p, chunk.x(), chunk.z()) != hide)
CraftbukkitWrapper.impl.sendChunk(p, chunk.x(), chunk.z());
}
} else {
return TechHider.State.SKIP;
}, 40);
}
private boolean bypass(Player p, int chunkX, int chunkZ){
if(Config.isReferee(p))
return true;
FightTeam ft = Fight.getPlayerTeam(p);
if(ft == null){
return Config.ArenaRegion.chunkOutside(chunkX, chunkZ);
}else if(ft.isBlue()){
return ft.canPlayerEntern(p) || Config.RedExtendRegion.chunkOutside(chunkX, chunkZ);
}else{
return ft.canPlayerEntern(p) || Config.BlueExtendRegion.chunkOutside(chunkX, chunkZ);
}
}
@Override
public boolean blockPrecise(Player player, int chunkX, int chunkY, int chunkZ) {
return FightSystem.getHullHider().blockPrecise(player, chunkX, chunkY, chunkZ);
}
private Region getHiddenRegion(Player player) {
if(Config.isReferee(player))
return Region.EMPTY;
FightTeam team = Fight.getPlayerTeam(player);
if(team == null)
return Config.ArenaRegion;
if(team.canPlayerEntern(player))
return Region.EMPTY;
return Fight.getOpposite(team).getExtendRegion();
}
}

Datei anzeigen

@ -26,6 +26,7 @@ import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.OneShotStateDependent;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.fightsystem.utils.Message;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -33,12 +34,27 @@ import org.bukkit.event.entity.EntityExplodeEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
public class WinconditionPercent extends Wincondition implements PrintableWincondition {
public class PercentWincondition extends Wincondition implements PrintableWincondition {
private final Map<FightTeam, TeamPercent> teamMap = new HashMap<>();
protected BooleanSupplier explosionFilter = () -> !Config.EnterStages.isEmpty() && Config.EnterStages.get(0) >= Wincondition.getTimeOverCountdown().getTimeLeft();
protected Predicate<Material> testBlock = type -> !Config.PercentBlocks.contains(type);
protected ToIntFunction<FightTeam> totalBlockCalc = team -> {
AtomicInteger blocks = new AtomicInteger();
team.getSchemRegion().forEach((x, y, z) -> {
if (testBlock.test(Config.world.getBlockAt(x, y, z).getType())) {
blocks.getAndIncrement();
}
});
return blocks.get();
};
protected Consumer<FightTeam> checkWin = team -> {
if (getPercent(team) >= Config.PercentWin) {
win(Fight.getOpposite(team), "WIN_PERCENT", team.getColoredName());
@ -46,7 +62,7 @@ public class WinconditionPercent extends Wincondition implements PrintableWincon
};
protected Consumer<FightTeam> postEnable = team -> {};
public WinconditionPercent(Winconditions wincondition, String windescription) {
public PercentWincondition(String windescription, Winconditions wincondition) {
super(windescription);
if (Config.ActiveWinconditions.contains(wincondition)) {
@ -58,7 +74,7 @@ public class WinconditionPercent extends Wincondition implements PrintableWincon
}
public Message getDisplay(FightTeam team) {
return new Message("BAR_PERCENT", team.getPrefix() + (Math.round(10000.0 * (1.0 - getPercent(team) / Config.PercentWin)) / 100.0));
return new Message("BAR_PERCENT", team.getPrefix() + (Math.round(100.0 * getPercent(team)) / 100.0));
}
public double getPercent(FightTeam team) {
@ -89,16 +105,12 @@ public class WinconditionPercent extends Wincondition implements PrintableWincon
@EventHandler
public void onEntityExplode(EntityExplodeEvent event) {
if (
event.getEntityType() == EntityType.FIREBALL ||
!team.getExtendRegion().inRegion(event.getEntity().getLocation()) ||
(!Config.PercentEntern && !Config.EnterStages.isEmpty() && Config.EnterStages.get(0) >= Wincondition.getTimeOverCountdown().getTimeLeft())
) {
if (event.getEntityType() == EntityType.FIREBALL || explosionFilter.getAsBoolean() || !team.getExtendRegion().inRegion(event.getEntity().getLocation())) {
return;
}
event.blockList().forEach(block -> {
if (Config.PercentBlocks.contains(block.getType()) == Config.PercentBlocksWhitelist) {
if (testBlock.test(block.getType())) {
currentBlocks--;
}
});
@ -107,11 +119,7 @@ public class WinconditionPercent extends Wincondition implements PrintableWincon
}
private void enable() {
totalBlocks = 0;
team.getSchemRegion().forEach((x, y, z) -> {
if (Config.PercentBlocks.contains(Config.world.getBlockAt(x, y, z).getType()) == Config.PercentBlocksWhitelist)
totalBlocks++;
});
totalBlocks = totalBlockCalc.applyAsInt(team);
currentBlocks = totalBlocks;
postEnable.accept(team);
}

Datei anzeigen

@ -24,7 +24,6 @@ import de.steamwar.fightsystem.countdown.Countdown;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.states.StateDependentCountdown;
import lombok.Getter;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
@ -35,10 +34,8 @@ import java.util.stream.Collectors;
public abstract class Wincondition {
@Getter
protected static WinconditionPercent percentWincondition = null;
protected static PercentWincondition percentWincondition = null;
protected static StateDependentCountdown timeOverCountdown = null;
@Getter
protected static final List<PrintableWincondition> printableWinconditions = new ArrayList<>();
private final String windescription;
@ -64,6 +61,14 @@ public abstract class Wincondition {
return Fight.getPlayerTeam((LivingEntity) player);
}
public static List<PrintableWincondition> getPrintableWinconditions(){
return printableWinconditions;
}
public static PercentWincondition getPercentWincondition() {
return percentWincondition;
}
protected void comparisonWin(ToDoubleFunction<FightTeam> evaluate, String winMessage, String tieMessage) {
double max = Fight.teams().stream().mapToDouble(evaluate).max().orElseThrow(() -> new SecurityException("No teams present"));
List<FightTeam> teams = Fight.teams().stream().filter(team -> evaluate.applyAsDouble(team) == max).collect(Collectors.toList());

Datei anzeigen

@ -19,13 +19,16 @@
package de.steamwar.fightsystem.winconditions;
import de.steamwar.fightsystem.events.TeamDeathEvent;
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.StateDependentListener;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class WinconditionAllDead extends Wincondition implements Listener {
@ -35,12 +38,25 @@ public class WinconditionAllDead extends Wincondition implements Listener {
}
@EventHandler
public void handlePlayerDeath(TeamDeathEvent event) {
FightTeam team = event.getFightPlayer().getTeam();
public void handlePlayerDeath(EntityDeathEvent event) {
handleDeath(event.getEntity());
}
if(team.getAlivePlayers() > 0)
@EventHandler
public void handlePlayerQuit(PlayerQuitEvent event) {
handleDeath(event.getPlayer());
}
private void handleDeath(Entity player){
FightTeam team = isTarget(player);
if(team == null)
return;
for(FightPlayer fp : team.getPlayers()) {
if(fp.isLiving() && fp.getEntity() != player)
return;
}
win(Fight.getOpposite(team), "WIN_ALL_DEAD", team.getPrefix());
}
}

Datei anzeigen

@ -0,0 +1,27 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.winconditions;
public class WinconditionBlacklistPercent extends PercentWincondition {
public WinconditionBlacklistPercent(){
super("RelativePercent", Winconditions.RELATIVE_PERCENT);
}
}

Datei anzeigen

@ -19,14 +19,16 @@
package de.steamwar.fightsystem.winconditions;
import de.steamwar.fightsystem.events.TeamDeathEvent;
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.StateDependentListener;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class WinconditionCaptainDead extends Wincondition implements Listener {
@ -36,12 +38,22 @@ public class WinconditionCaptainDead extends Wincondition implements Listener {
}
@EventHandler
public void handlePlayerDeath(TeamDeathEvent event) {
FightPlayer leader = event.getFightPlayer();
if(!leader.isLeader())
public void handlePlayerDeath(EntityDeathEvent event) {
handleDeath(event.getEntity());
}
@EventHandler
public void handlePlayerQuit(PlayerQuitEvent event) {
handleDeath(event.getPlayer());
}
private void handleDeath(Entity player){
FightTeam team = isTarget(player);
if(team == null)
return;
FightTeam team = leader.getTeam();
win(Fight.getOpposite(team), "WIN_LEADER_DEAD", team.getPrefix() + leader.getEntity().getName());
if(team.isPlayerLeader((LivingEntity) player)) {
win(Fight.getOpposite(team), "WIN_LEADER_DEAD", team.getPrefix() + team.getLeader().getEntity().getName());
}
}
}

Datei anzeigen

@ -0,0 +1,30 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.winconditions;
public class WinconditionPercentSystem extends PercentWincondition {
public WinconditionPercentSystem() {
super("Percent", Winconditions.PERCENT_SYSTEM);
totalBlockCalc = team -> team.getSchemRegion().volume();
explosionFilter = () -> false;
}
}

Datei anzeigen

@ -36,12 +36,12 @@ import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.Map;
public class WinconditionPoints extends WinconditionPercent implements Listener {
public class WinconditionPoints extends PercentWincondition implements Listener {
private final Map<FightTeam, TeamPoints> teamMap = new HashMap<>();
public WinconditionPoints(){
super(Winconditions.POINTS, "Points");
super("Points", Winconditions.POINTS);
checkWin = team -> {};
postEnable = this::pointInit;

Datei anzeigen

@ -35,7 +35,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class WinconditionPointsAirShip extends WinconditionPercent implements Listener {
public class WinconditionPointsAirShip extends PercentWincondition implements Listener {
private double[] as = new double[] {
0.5,
@ -56,7 +56,7 @@ public class WinconditionPointsAirShip extends WinconditionPercent implements Li
private final Map<FightTeam, TeamPoints> teamMap = new HashMap<>();
public WinconditionPointsAirShip(){
super(Winconditions.POINTS_AIRSHIP, "Points");
super("Points", Winconditions.POINTS_AIRSHIP);
checkWin = team -> {
if (teamMap.get(team).getPoints() > TeamPoints.WIN_POINTS) {

Datei anzeigen

@ -0,0 +1,31 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2021 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.winconditions;
import de.steamwar.fightsystem.Config;
public class WinconditionWhitelistPercent extends PercentWincondition {
public WinconditionWhitelistPercent() {
super("WhitelistPercent", Winconditions.WHITELIST_PERCENT);
testBlock = Config.PercentBlocks::contains;
}
}

Datei anzeigen

@ -28,6 +28,8 @@ public enum Winconditions {
CAPTAIN_DEAD,
PERCENT_SYSTEM,
WHITELIST_PERCENT,
RELATIVE_PERCENT,
POINTS,
POINTS_AIRSHIP,
@ -37,7 +39,5 @@ public enum Winconditions {
HELLS_BELLS,
METEOR,
AMONG_US,
PERSISTENT_DAMAGE,
TNT_DISTRIBUTION
AMONG_US
}

Datei anzeigen

@ -26,6 +26,4 @@ commands:
win:
resetwg:
resettb:
tpslimit:
tpswarp:
unrank:

Datei anzeigen

@ -46,6 +46,11 @@ mainClassName = ''
allprojects {
repositories {
mavenCentral()
jcenter()
maven {
url = uri("https://repo.codemc.io/repository/maven-snapshots/")
}
maven {
url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/')

0
gradlew vendored Ausführbare Datei → Normale Datei
Datei anzeigen