Add Winconditions.TIMED_DAMAGE_TECH_KO and Winconditions.RANDOM_ROTATE

This commit is contained in:
2025-07-13 16:46:11 +02:00
parent 3410dd5a4b
commit 868ba4073b
10 changed files with 196 additions and 14 deletions
@@ -108,6 +108,7 @@ public class Config {
public static final boolean PercentEntern; public static final boolean PercentEntern;
public static final boolean PercentBlocksWhitelist; public static final boolean PercentBlocksWhitelist;
public static final Set<Material> PercentBlocks; public static final Set<Material> PercentBlocks;
public static final int TechKoTime;
//default kits //default kits
public static final String MemberDefault; public static final String MemberDefault;
@@ -209,6 +210,7 @@ public class Config {
PercentEntern = config.getBoolean("WinConditionParams.PercentEntern", true); PercentEntern = config.getBoolean("WinConditionParams.PercentEntern", true);
PercentBlocksWhitelist = config.getBoolean("WinConditionParams.BlocksWhitelist", false); PercentBlocksWhitelist = config.getBoolean("WinConditionParams.BlocksWhitelist", false);
PercentBlocks = Collections.unmodifiableSet(config.getStringList("WinConditionParams.Blocks").stream().map(Material::valueOf).collect(Collectors.toSet())); PercentBlocks = Collections.unmodifiableSet(config.getStringList("WinConditionParams.Blocks").stream().map(Material::valueOf).collect(Collectors.toSet()));
TechKoTime = config.getInt("WinConditionParams.TechKoTime", 90);
EnterStages = Collections.unmodifiableList(config.getIntegerList("EnterStages")); EnterStages = Collections.unmodifiableList(config.getIntegerList("EnterStages"));
AllowMissiles = config.getBoolean("Arena.AllowMissiles", !EnterStages.isEmpty()); AllowMissiles = config.getBoolean("Arena.AllowMissiles", !EnterStages.isEmpty());
@@ -191,6 +191,7 @@ BAR_POINTS_OF={0}§8/§7{1} §8Points
BAR_PERCENT={0}§8% BAR_PERCENT={0}§8%
BAR_CANNONS={0} §8Cannons BAR_CANNONS={0} §8Cannons
BAR_WATER={0} §8Water BAR_WATER={0} §8Water
BAR_SECONDS={0}§8s
# Winconditions # Winconditions
@@ -19,20 +19,15 @@
package de.steamwar.fightsystem.fight; package de.steamwar.fightsystem.fight;
import com.comphenix.tinyprotocol.TinyProtocol;
import com.mojang.authlib.GameProfile;
import de.steamwar.core.Core; import de.steamwar.core.Core;
import de.steamwar.core.ProtocolWrapper;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.record.GlobalRecorder; import de.steamwar.fightsystem.record.GlobalRecorder;
import de.steamwar.fightsystem.utils.RandomSeed;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
@@ -40,6 +35,8 @@ import java.util.HashSet;
public class Fight { public class Fight {
private Fight(){} private Fight(){}
@Getter
private static final RandomSeed randomSeed = new RandomSeed();
@Getter @Getter
private static final FightTeam redTeam = new FightTeam(Config.TeamRedName, Config.TeamRedColor, Config.TeamRedSpawn, Config.RedPasteRegion, Config.RedExtendRegion, Config.RedRotate, false, Config.RedLeader); private static final FightTeam redTeam = new FightTeam(Config.TeamRedName, Config.TeamRedColor, Config.TeamRedSpawn, Config.RedPasteRegion, Config.RedExtendRegion, Config.RedRotate, false, Config.RedLeader);
@Getter @Getter
@@ -31,6 +31,7 @@ import de.steamwar.fightsystem.states.StateDependent;
import de.steamwar.fightsystem.utils.ColorConverter; import de.steamwar.fightsystem.utils.ColorConverter;
import de.steamwar.fightsystem.utils.Region; import de.steamwar.fightsystem.utils.Region;
import de.steamwar.fightsystem.utils.WorldeditWrapper; import de.steamwar.fightsystem.utils.WorldeditWrapper;
import de.steamwar.fightsystem.winconditions.Winconditions;
import de.steamwar.sql.SchematicData; import de.steamwar.sql.SchematicData;
import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SchematicType; import de.steamwar.sql.SchematicType;
@@ -141,6 +142,11 @@ public class FightSchematic extends StateDependent {
team.teleportToSpawn(); team.teleportToSpawn();
boolean rotate = this.rotate;
if (Config.ActiveWinconditions.contains(Winconditions.RANDOM_ROTATE)) {
rotate = Fight.getRandomSeed().getRandom(schematic).nextBoolean();
}
Vector dims = WorldeditWrapper.impl.getDimensions(clipboard); Vector dims = WorldeditWrapper.impl.getDimensions(clipboard);
WorldeditWrapper.impl.pasteClipboard( WorldeditWrapper.impl.pasteClipboard(
clipboard, clipboard,
@@ -20,7 +20,6 @@
package de.steamwar.fightsystem.record; package de.steamwar.fightsystem.record;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import de.steamwar.core.Core;
import de.steamwar.core.TrickyTrialsWrapper; import de.steamwar.core.TrickyTrialsWrapper;
import de.steamwar.core.WorldEditWrapper; import de.steamwar.core.WorldEditWrapper;
import de.steamwar.entity.REntity; import de.steamwar.entity.REntity;
@@ -153,6 +152,7 @@ public class PacketProcessor implements Listener {
packetDecoder[0xc6] = this::winMessage; packetDecoder[0xc6] = this::winMessage;
packetDecoder[0xc7] = this::bossBarMessage; packetDecoder[0xc7] = this::bossBarMessage;
packetDecoder[0xef] = source::readUTF; packetDecoder[0xef] = source::readUTF;
packetDecoder[0xfd] = this::randomSeed;
packetDecoder[0xff] = this::tick; packetDecoder[0xff] = this::tick;
execSync(FightWorld::forceLoad); execSync(FightWorld::forceLoad);
@@ -638,6 +638,14 @@ public class PacketProcessor implements Listener {
execSync(() -> entities.get(entityId).setOnFire(perma)); execSync(() -> entities.get(entityId).setOnFire(perma));
} }
private void randomSeed() throws IOException {
long seed = source.readLong();
execSync(() -> {
Fight.getRandomSeed().setSeed(seed);
});
}
private void tick(){ private void tick(){
execSync(entityServer::tick); execSync(entityServer::tick);
@@ -133,6 +133,7 @@ public interface Recorder {
* WinPacket (0xc6) + byte team + Message subtitle * WinPacket (0xc6) + byte team + Message subtitle
* BossBarPacket (0xc7) + double leftBlueProgress, leftRedProgress + Message leftBlueText, leftRedText * BossBarPacket (0xc7) + double leftBlueProgress, leftRedProgress + Message leftBlueText, leftRedText
* *
* RandomSeed (0xfd) + long seed
* CommentPacket (0xfe) + String comment * CommentPacket (0xfe) + String comment
* TickPacket (0xff) * TickPacket (0xff)
* *
@@ -310,6 +311,10 @@ public interface Recorder {
write(0xc6, bTeam, new Message(subtitle, params)); write(0xc6, bTeam, new Message(subtitle, params));
} }
default void seed(long seed) {
write(0xfd, seed);
}
default void tick(){ default void tick(){
write(0xff); write(0xff);
} }
@@ -339,6 +344,8 @@ public interface Recorder {
stream.writeShort((Short)o); stream.writeShort((Short)o);
else if(o instanceof Integer) else if(o instanceof Integer)
stream.writeInt((Integer)o); stream.writeInt((Integer)o);
else if(o instanceof Long)
stream.writeLong((Long)o);
else if(o instanceof Float) else if(o instanceof Float)
stream.writeFloat((Float)o); stream.writeFloat((Float)o);
else if(o instanceof Double) else if(o instanceof Double)
@@ -0,0 +1,45 @@
/*
* 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.utils;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.record.GlobalRecorder;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.OneShotStateDependent;
import lombok.Setter;
import java.util.Random;
public class RandomSeed {
@Setter
private long seed;
public RandomSeed() {
new OneShotStateDependent(ArenaMode.AntiReplay, FightState.PreSchemSetup, () -> {
this.seed = System.nanoTime();
GlobalRecorder.getInstance().seed(seed);
});
}
public Random getRandom(int derivation) {
return new Random(seed ^ new Random(derivation).nextLong());
}
}
@@ -20,6 +20,7 @@
package de.steamwar.fightsystem.winconditions; package de.steamwar.fightsystem.winconditions;
import de.steamwar.core.TrickyTrialsWrapper; import de.steamwar.core.TrickyTrialsWrapper;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.countdown.Countdown; import de.steamwar.fightsystem.countdown.Countdown;
import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.fight.FightTeam;
@@ -30,7 +31,6 @@ import de.steamwar.fightsystem.states.StateDependentTask;
import de.steamwar.fightsystem.utils.Message; import de.steamwar.fightsystem.utils.Message;
import de.steamwar.fightsystem.utils.SWSound; import de.steamwar.fightsystem.utils.SWSound;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.EntityExplodeEvent;
@@ -41,8 +41,7 @@ import java.util.Map;
public class WinconditionTimeTechKO extends Wincondition implements Listener { public class WinconditionTimeTechKO extends Wincondition implements Listener {
private static final int TECH_KO_TIME_IN_S = 90; private static final int TECH_KO_HALF_TIME = Config.TechKoTime/2;
private static final int TECH_KO_HALF_TIME = TECH_KO_TIME_IN_S/2;
private final Map<Integer, FightTeam> spawnLocations = new HashMap<>(); private final Map<Integer, FightTeam> spawnLocations = new HashMap<>();
private final Map<FightTeam, TechKOCountdown> countdowns = new HashMap<>(); private final Map<FightTeam, TechKOCountdown> countdowns = new HashMap<>();
@@ -51,9 +50,9 @@ public class WinconditionTimeTechKO extends Wincondition implements Listener {
public WinconditionTimeTechKO(){ public WinconditionTimeTechKO(){
super("TechKO"); super("TechKO");
new StateDependentListener(Winconditions.TIME_TECH_KO, FightState.Running, this); new StateDependentListener(Winconditions.TIMED_DAMAGE_TECH_KO, FightState.Running, this);
new StateDependentTask(Winconditions.TIME_TECH_KO, FightState.Running, this::run, 20, 20); new StateDependentTask(Winconditions.TIMED_DAMAGE_TECH_KO, FightState.Running, this::run, 20, 20);
new StateDependent(Winconditions.TIME_TECH_KO, FightState.Running) { new StateDependent(Winconditions.TIMED_DAMAGE_TECH_KO, FightState.Running) {
@Override @Override
public void enable() { public void enable() {
Fight.teams().forEach(team -> currentTime.put(team, TECH_KO_HALF_TIME)); Fight.teams().forEach(team -> currentTime.put(team, TECH_KO_HALF_TIME));
@@ -0,0 +1,115 @@
/*
* 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;
import de.steamwar.core.TrickyTrialsWrapper;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.countdown.Countdown;
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.fightsystem.utils.Message;
import de.steamwar.fightsystem.utils.SWSound;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityExplodeEvent;
import java.util.HashMap;
import java.util.Map;
public class WinconditionTimedDamageTechKO extends Wincondition implements PrintableWincondition, Listener {
private final Map<FightTeam, TechKOCountdown> countdowns = new HashMap<>();
public WinconditionTimedDamageTechKO() {
super("TechKO");
new StateDependentListener(Winconditions.TIMED_DAMAGE_TECH_KO, FightState.Running, this);
new StateDependent(Winconditions.TIMED_DAMAGE_TECH_KO, FightState.Running) {
@Override
public void enable() {
Fight.teams().forEach(team -> {
TechKOCountdown countdown = new TechKOCountdown(team, Config.TechKoTime);
countdowns.put(team, countdown);
countdown.enable();
});
}
@Override
public void disable() {
countdowns.values().forEach(Countdown::disable);
countdowns.clear();
}
}.register();
}
@Override
public Message getDisplay(FightTeam team) {
return new Message("BAR_SECONDS", team.getPrefix() + countdowns.get(team).getTimeLeft());
}
@EventHandler
public void onExplode(EntityExplodeEvent e) {
if (e.getEntityType() != TrickyTrialsWrapper.impl.getTntEntityType())
return;
Location location = e.getLocation();
TechKOCountdown countdown = null;
FightTeam fightTeam = null;
for (FightTeam team : Fight.teams()) {
FightTeam current = Fight.getOpposite(team);
if (current.getExtendRegion().inRegion(location)) {
fightTeam = current;
countdown = countdowns.get(team);
break;
}
}
if (fightTeam == null) {
return;
}
FightTeam finalFightTeam = fightTeam;
TechKOCountdown finalCountdown = countdown;
e.blockList().forEach(block -> {
if (block.isEmpty()) return;
if (finalFightTeam.getExtendRegion().inRegion(block)) {
finalCountdown.disable();
finalCountdown.enable();
}
});
}
private class TechKOCountdown extends Countdown {
private final FightTeam team;
public TechKOCountdown(FightTeam team, int countdownTime) {
super(countdownTime, new Message("TECHKO_COUNTDOWN", team.getColoredName()), SWSound.BLOCK_NOTE_PLING, false);
this.team = team;
}
@Override
public void countdownFinished() {
win(Fight.getOpposite(team), "WIN_TECHKO", team.getColoredName());
}
}
}
@@ -31,7 +31,8 @@ public enum Winconditions {
POINTS, POINTS,
POINTS_AIRSHIP, POINTS_AIRSHIP,
TIME_TECH_KO, DAMAGE_TECH_KO,
TIMED_DAMAGE_TECH_KO,
WATER_TECH_KO, WATER_TECH_KO,
PUMPKIN_TECH_KO, PUMPKIN_TECH_KO,
@@ -41,4 +42,5 @@ public enum Winconditions {
PERSISTENT_DAMAGE, PERSISTENT_DAMAGE,
TNT_DISTRIBUTION, TNT_DISTRIBUTION,
NO_GRAVITY, NO_GRAVITY,
RANDOM_ROTATE,
} }