SteamWar/FightSystem
Archiviert
13
1

Add ranked rework
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Dieser Commit ist enthalten in:
yoyosource 2022-03-09 15:30:19 +01:00
Ursprung 72f3aed8ba
Commit f4ffd17c55
8 geänderte Dateien mit 101 neuen und 145 gelöschten Zeilen

Datei anzeigen

@ -25,7 +25,6 @@ import java.util.Set;
public enum ArenaMode { public enum ArenaMode {
NORMAL, NORMAL,
RANKED,
EVENT, EVENT,
TEST, TEST,
CHECK, CHECK,
@ -38,7 +37,6 @@ public enum ArenaMode {
public static final Set<ArenaMode> Check = Collections.unmodifiableSet(EnumSet.of(CHECK)); public static final Set<ArenaMode> Check = Collections.unmodifiableSet(EnumSet.of(CHECK));
public static final Set<ArenaMode> Event = Collections.unmodifiableSet(EnumSet.of(EVENT)); public static final Set<ArenaMode> Event = Collections.unmodifiableSet(EnumSet.of(EVENT));
public static final Set<ArenaMode> Test = Collections.unmodifiableSet(EnumSet.of(TEST, CHECK)); public static final Set<ArenaMode> Test = Collections.unmodifiableSet(EnumSet.of(TEST, CHECK));
public static final Set<ArenaMode> Ranked = Collections.unmodifiableSet(EnumSet.of(RANKED));
public static final Set<ArenaMode> Prepare = Collections.unmodifiableSet(EnumSet.of(PREPARE)); public static final Set<ArenaMode> Prepare = Collections.unmodifiableSet(EnumSet.of(PREPARE));
public static final Set<ArenaMode> Replay = Collections.unmodifiableSet(EnumSet.of(REPLAY, TEST)); public static final Set<ArenaMode> Replay = Collections.unmodifiableSet(EnumSet.of(REPLAY, TEST));
@ -46,9 +44,9 @@ public enum ArenaMode {
public static final Set<ArenaMode> AntiTest = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(TEST, CHECK))); public static final Set<ArenaMode> AntiTest = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(TEST, CHECK)));
public static final Set<ArenaMode> AntiEvent = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(EVENT))); public static final Set<ArenaMode> AntiEvent = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(EVENT)));
public static final Set<ArenaMode> AntiPrepare = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(PREPARE))); public static final Set<ArenaMode> AntiPrepare = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(PREPARE)));
public static final Set<ArenaMode> VariableTeams = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(RANKED, EVENT, REPLAY))); public static final Set<ArenaMode> VariableTeams = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(EVENT, REPLAY)));
public static final Set<ArenaMode> RankedEvent = Collections.unmodifiableSet(EnumSet.of(RANKED, EVENT, REPLAY)); public static final Set<ArenaMode> RankedEvent = Collections.unmodifiableSet(EnumSet.of(EVENT, REPLAY));
public static final Set<ArenaMode> Restartable = Collections.unmodifiableSet(EnumSet.of(NORMAL, RANKED)); public static final Set<ArenaMode> Restartable = Collections.unmodifiableSet(EnumSet.of(NORMAL));
public static final Set<ArenaMode> NotRestartable = Collections.unmodifiableSet(EnumSet.of(EVENT, REPLAY)); public static final Set<ArenaMode> NotRestartable = Collections.unmodifiableSet(EnumSet.of(EVENT, REPLAY));
public static final Set<ArenaMode> SoloLeader = Collections.unmodifiableSet(EnumSet.of(TEST, CHECK, PREPARE)); public static final Set<ArenaMode> SoloLeader = Collections.unmodifiableSet(EnumSet.of(TEST, CHECK, PREPARE));
public static final Set<ArenaMode> NotOnBau = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(TEST, CHECK, PREPARE, REPLAY))); public static final Set<ArenaMode> NotOnBau = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(TEST, CHECK, PREPARE, REPLAY)));

Datei anzeigen

@ -92,7 +92,7 @@ public class Config {
public static final String TeamChatDetection; public static final String TeamChatDetection;
public static final UUID BlueLeader; public static final UUID BlueLeader;
public static final UUID RedLeader; public static final UUID RedLeader;
public static final boolean Ranked; public static final boolean RankedEnabled;
//Active win conditions //Active win conditions
public static final Set<Winconditions> ActiveWinconditions; public static final Set<Winconditions> ActiveWinconditions;
@ -150,6 +150,8 @@ public class Config {
} }
FileConfiguration worldconfig = YamlConfiguration.loadConfiguration(worldConfigFile); FileConfiguration worldconfig = YamlConfiguration.loadConfiguration(worldConfigFile);
RankedEnabled = config.getBoolean("Server.Ranked", false);
NoPlayerOnlineDuration = config.getInt("Times.NoPlayersOnlineDuration", 30); NoPlayerOnlineDuration = config.getInt("Times.NoPlayersOnlineDuration", 30);
PreSchemPasteDuration = config.getInt("Times.PreSchemPasteDuration", 120); PreSchemPasteDuration = config.getInt("Times.PreSchemPasteDuration", 120);
SetupDuration = config.getInt("Times.SetupDuration", 300); SetupDuration = config.getInt("Times.SetupDuration", 300);
@ -370,12 +372,9 @@ public class Config {
CheckSchemID = Integer.parseInt(System.getProperty("checkSchemID", "0")); CheckSchemID = Integer.parseInt(System.getProperty("checkSchemID", "0"));
PrepareSchemID = Integer.parseInt(System.getProperty("prepareSchemID", "0")); PrepareSchemID = Integer.parseInt(System.getProperty("prepareSchemID", "0"));
Ranked = Boolean.parseBoolean(System.getProperty("ranked", "false"));
ReplayID = Integer.parseInt(System.getProperty("replay", "0")); ReplayID = Integer.parseInt(System.getProperty("replay", "0"));
if(Ranked){ if(CheckSchemID != 0){
mode = ArenaMode.RANKED;
}else if(CheckSchemID != 0){
mode = ArenaMode.CHECK; mode = ArenaMode.CHECK;
}else if(PrepareSchemID != 0){ }else if(PrepareSchemID != 0){
mode = ArenaMode.PREPARE; mode = ArenaMode.PREPARE;

Datei anzeigen

@ -87,7 +87,6 @@ public class FightSystem extends JavaPlugin {
new PrepareSchem(); new PrepareSchem();
new TestJoin(); new TestJoin();
new NormalJoin(); new NormalJoin();
new RankedJoin();
new RunningWorldInteraction(); new RunningWorldInteraction();
new PersonalKitCreator(); new PersonalKitCreator();
new ArrowStopper(); new ArrowStopper();
@ -114,7 +113,6 @@ public class FightSystem extends JavaPlugin {
new WinconditionHeartRatioTimeout(); new WinconditionHeartRatioTimeout();
new WinconditionTimeTechKO(); new WinconditionTimeTechKO();
new EventTeamOffWincondition(); new EventTeamOffWincondition();
new RankedPlayerLeftWincondition();
new WinconditionPercentTimeout(); new WinconditionPercentTimeout();
new HellsBells(); new HellsBells();

Datei anzeigen

@ -180,7 +180,7 @@ UI_PLAYER_LEAVES=
UI_LEADER_JOINS=§a§l» {0}Leader {1} UI_LEADER_JOINS=§a§l» {0}Leader {1}
UI_PLAYER_DEATH={0}{1} §7ist gestorben UI_PLAYER_DEATH={0}{1} §7ist gestorben
UI_PLAYER_LEAVE={0}{1} §7hat den Kampf verlassen UI_PLAYER_LEAVE={0}{1} §7hat den Kampf verlassen
UI_ELO=§7ELO von {0}{1}§8: §7{2}§8»§e{3} UI_ELO_PLAYER=§7Elo§8: §7{0}§8»§7{1}
UI_WIN={0}Sieg {1} UI_WIN={0}Sieg {1}
UI_DRAW=§7Unentschieden UI_DRAW=§7Unentschieden
@ -232,7 +232,6 @@ WIN_FIGHTLEADER=
WIN_PERCENT={0} §7zu beschädigt WIN_PERCENT={0} §7zu beschädigt
WIN_OFFLINE_BOTH=§7Beide Teams offline WIN_OFFLINE_BOTH=§7Beide Teams offline
WIN_OFFLINE={0} §7offline WIN_OFFLINE={0} §7offline
WIN_RANKED_LEFT={0} §7hat den Kampf verlassen
WIN_ALL_DEAD={0}Alle Spieler kampfunfähig WIN_ALL_DEAD={0}Alle Spieler kampfunfähig
WIN_LEADER_DEAD={0} kampfunfähig WIN_LEADER_DEAD={0} kampfunfähig
WIN_TIME_OVER=§7Zeit abgelaufen WIN_TIME_OVER=§7Zeit abgelaufen

Datei anzeigen

@ -45,6 +45,7 @@ public abstract class Countdown {
private final boolean level; private final boolean level;
protected int time; protected int time;
protected int timeElapsed;
private BukkitTask task = null; private BukkitTask task = null;
public abstract void countdownFinished(); public abstract void countdownFinished();
@ -110,8 +111,13 @@ public abstract class Countdown {
return time; return time;
} }
public int getTimeElapsed(){
return timeElapsed;
}
private void count() { private void count() {
time--; time--;
timeElapsed++;
show(); show();
} }

Datei anzeigen

@ -1,52 +0,0 @@
/*
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.Config;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentListener;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
public class RankedJoin implements Listener {
public RankedJoin() {
new StateDependentListener(ArenaMode.Ranked, FightState.PreLeaderSetup, this);
}
@EventHandler
public void handlePlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
FightTeam fightTeam = Fight.getPlayerTeam(player);
if (fightTeam == null) {
if(!player.getUniqueId().equals(Config.RedLeader) && Fight.getBlueTeam().canbeLeader(player)) {
Fight.getBlueTeam().addMember(player);
}else if(Fight.getRedTeam().canbeLeader(player)) {
Fight.getRedTeam().addMember(player);
}
}
}
}

Datei anzeigen

@ -39,6 +39,9 @@ import java.io.FileInputStream;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import static de.steamwar.sql.Fight.create; import static de.steamwar.sql.Fight.create;
@ -61,7 +64,7 @@ public class FightStatistics {
new OneShotStateDependent(ArenaMode.SeriousFight, FightState.Spectate, () -> Bukkit.getScheduler().runTask(FightSystem.getPlugin(), this::disable)); new OneShotStateDependent(ArenaMode.SeriousFight, FightState.Spectate, () -> Bukkit.getScheduler().runTask(FightSystem.getPlugin(), this::disable));
} }
private void enable(){ private void enable() {
starttime = Timestamp.from(Instant.now()); starttime = Timestamp.from(Instant.now());
} }
@ -84,33 +87,43 @@ public class FightStatistics {
int win = 0; int win = 0;
double blueResult; double blueResult;
if(winner == Fight.getBlueTeam()) { if (winner == Fight.getBlueTeam()) {
win = 1; win = 1;
blueResult = 1; blueResult = 1;
}else if(winner == Fight.getRedTeam()) { } else if (winner == Fight.getRedTeam()) {
win = 2; win = 2;
blueResult = 0; blueResult = 0;
}else{ } else {
blueResult = 0.5; blueResult = 0.5;
} }
Integer blueSchem; Integer blueSchem;
Integer blueSchemRank;
Integer redSchem; Integer redSchem;
try{ Integer redSchemRank;
blueSchem = SchematicNode.getSchematicNode(Fight.getBlueTeam().getSchematic()).getId(); try {
}catch(SecurityException e){ SchematicNode schematicNode = SchematicNode.getSchematicNode(Fight.getBlueTeam().getSchematic());
blueSchem = schematicNode.getId();
blueSchemRank = schematicNode.getRank();
} catch (SecurityException e) {
blueSchem = null; blueSchem = null;
blueSchemRank = null;
} }
try{ try {
redSchem = SchematicNode.getSchematicNode(Fight.getRedTeam().getSchematic()).getId(); SchematicNode schematicNode = SchematicNode.getSchematicNode(Fight.getRedTeam().getSchematic());
}catch(SecurityException e){ redSchem = schematicNode.getId();
redSchemRank = schematicNode.getRank();
} catch (SecurityException e) {
redSchem = null; redSchem = null;
redSchemRank = null;
} }
int remainingTime = 0; int remainingTime = 0;
int timeElapsed = 0;
Countdown timeOverCountdown = Wincondition.getTimeOverCountdown(); Countdown timeOverCountdown = Wincondition.getTimeOverCountdown();
if(timeOverCountdown != null){ if (timeOverCountdown != null) {
remainingTime = timeOverCountdown.getTimeLeft(); remainingTime = timeOverCountdown.getTimeLeft();
timeElapsed = timeOverCountdown.getTimeElapsed();
} }
try { try {
@ -122,43 +135,88 @@ public class FightStatistics {
for (FightPlayer fp : Fight.getRedTeam().getPlayers()) for (FightPlayer fp : Fight.getRedTeam().getPlayers())
savePlayerStats(fp, fightId); savePlayerStats(fp, fightId);
if(ArenaMode.Event.contains(Config.mode)) { if (ArenaMode.Event.contains(Config.mode)) {
FightSystem.getEventFight().setFight(fightId); FightSystem.getEventFight().setFight(fightId);
} }
try { try {
setReplay(fightId, new FileInputStream(FileRecorder.getFile())); setReplay(fightId, new FileInputStream(FileRecorder.getFile()));
}catch(Exception e){ } catch (Exception e) {
Bukkit.getLogger().log(Level.INFO, "Failed to save replay", e); Bukkit.getLogger().log(Level.INFO, "Failed to save replay", e);
} }
}catch(Exception e){ } catch (Exception e) {
Bukkit.getLogger().log(Level.SEVERE, "Failed to save statistics", e); Bukkit.getLogger().log(Level.SEVERE, "Failed to save statistics", e);
} }
replayLock = false; replayLock = false;
if(Config.Ranked){ calculateEloIfNeeded(timeElapsed, blueSchemRank, redSchemRank, blueResult, gameMode);
int blueElo = Elo.getElo(blueLeader, gameMode); }
int redElo = Elo.getElo(redLeader, gameMode);
double redWinExpectation = 1 / (1 + Math.pow(10, (blueElo - redElo) / 400f)); private void calculateEloIfNeeded(int timeElapsed, Integer blueSchemRank, Integer redSchemRank, double blueResult, String gameMode) {
double blueWinExpectation = 1 / (1 + Math.pow(10, (redElo - blueElo) / 400f)); if (!Config.RankedEnabled) {
int newBlueElo = (int) Math.round(blueElo + K * (blueResult - blueWinExpectation)); return;
int newRedElo = (int) Math.round(redElo + K * (1 - blueResult - redWinExpectation)); }
Elo.setElo(blueLeader, gameMode, newBlueElo);
Elo.setElo(redLeader, gameMode, newRedElo); if (timeElapsed < 30) { // Too short fights are not worth elo change
FightSystem.broadcast("UI_ELO", Fight.getBlueTeam().getPrefix(), SteamwarUser.get(blueLeader).getUserName(), blueElo, newBlueElo); return;
FightSystem.broadcast("UI_ELO", Fight.getRedTeam().getPrefix(), SteamwarUser.get(redLeader).getUserName(), redElo, newRedElo); }
if (blueSchemRank == null || redSchemRank == null) { // Schematics are not ranked
return;
}
if (blueSchemRank != redSchemRank) { // Different schematics ranks are not worth elo change
return;
}
Collection<FightPlayer> bluePlayers = Fight.getBlueTeam().getPlayers();
Collection<FightPlayer> redPlayers = Fight.getRedTeam().getPlayers();
double playerDiff = 1 - (Math.min(bluePlayers.size(), redPlayers.size()) / (double) Math.max(bluePlayers.size(), redPlayers.size()));
if (playerDiff >= 0.4) { // Too many players, not worth elo change
return;
}
int blueElo = 0;
int redElo = 0;
Map<FightPlayer, Integer> blueElos = new HashMap<>();
Map<FightPlayer, Integer> redElos = new HashMap<>();
for (FightPlayer fp : bluePlayers) {
int elo = Elo.getElo(SteamwarUser.get(fp.getPlayer()).getId(), gameMode);
blueElo += elo;
blueElos.put(fp, elo);
}
for (FightPlayer fp : redPlayers) {
int elo = Elo.getElo(SteamwarUser.get(fp.getPlayer()).getId(), gameMode);
redElo += elo;
redElos.put(fp, elo);
}
double redWinExpectation = 1 / (1 + Math.pow(10, (blueElo - redElo) / 600f));
double blueWinExpectation = 1 / (1 + Math.pow(10, (redElo - blueElo) / 600f));
double diffBlueElo = K * (blueResult - blueWinExpectation);
double diffRedElo = K * (1 - blueResult - redWinExpectation);
for (FightPlayer fp : bluePlayers) {
int nElo = (int) Math.round(blueElos.get(fp) + diffBlueElo / bluePlayers.size());
Elo.setElo(SteamwarUser.get(fp.getPlayer()).getId(), gameMode, nElo);
FightSystem.getMessage().send("UI_ELO_PLAYER", fp.getPlayer(), redElos.get(fp), nElo);
}
for (FightPlayer fp : redPlayers) {
int nElo = (int) Math.round(redElos.get(fp) + diffRedElo / redPlayers.size());
Elo.setElo(SteamwarUser.get(fp.getPlayer()).getId(), gameMode, nElo);
FightSystem.getMessage().send("UI_ELO_PLAYER", fp.getPlayer(), redElos.get(fp), nElo);
} }
} }
private int getLeader(FightTeam team){ private int getLeader(FightTeam team) {
if(team.getLeader() != null) if (team.getLeader() != null)
return SteamwarUser.get(team.getLeader().getPlayer().getUniqueId()).getId(); return SteamwarUser.get(team.getLeader().getPlayer().getUniqueId()).getId();
else if(team.getDesignatedLeader() != null) else if (team.getDesignatedLeader() != null)
return SteamwarUser.get(team.getDesignatedLeader()).getId(); return SteamwarUser.get(team.getDesignatedLeader()).getId();
return 0; return 0;
} }
private void savePlayerStats(FightPlayer fp, int fightId){ private void savePlayerStats(FightPlayer fp, int fightId) {
SteamwarUser user = SteamwarUser.get(fp.getPlayer().getUniqueId()); SteamwarUser user = SteamwarUser.get(fp.getPlayer().getUniqueId());
de.steamwar.sql.FightPlayer.create(fightId, user.getId(), fp.getTeam().isBlue(), fp.getKit().getName(), fp.getKills(), !fp.isLiving()); de.steamwar.sql.FightPlayer.create(fightId, user.getId(), fp.getTeam().isBlue(), fp.getKit().getName(), fp.getKills(), !fp.isLiving());
} }

Datei anzeigen

@ -1,50 +0,0 @@
/*
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.fightsystem.ArenaMode;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentListener;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
public class RankedPlayerLeftWincondition extends Wincondition implements Listener {
public RankedPlayerLeftWincondition(){
super("LeaderQuit");
new StateDependentListener(ArenaMode.Ranked, FightState.Setup, this);
}
@EventHandler
public void handlePlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
FightTeam team = isTarget(player);
if(team == null)
return;
if(team.isPlayerLeader(player)) {
win(Fight.getOpposite(team), "WIN_RANKED_LEFT", team.getPrefix() + team.getLeader().getPlayer().getName());
}
}
}