SteamWar/BungeeCore
Archiviert
13
2

Merge pull request 'Add new rank system' (#303) from Ranked into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Reviewed-on: #303
Reviewed-by: Lixfel <lixfel@steamwar.de>
Dieser Commit ist enthalten in:
Lixfel 2022-03-10 11:45:38 +01:00
Commit 9cb0378346
10 geänderte Dateien mit 172 neuen und 303 gelöschten Zeilen

Datei anzeigen

@ -116,7 +116,6 @@ public class BungeeCore extends Plugin {
new BugCommand(); new BugCommand();
new WhoisCommand(); new WhoisCommand();
new RegelnCommand(); new RegelnCommand();
new RankCommand();
new IgnoreCommand(); new IgnoreCommand();
new UnIgnoreCommand(); new UnIgnoreCommand();
new PollresultCommand(); new PollresultCommand();
@ -144,7 +143,6 @@ public class BungeeCore extends Plugin {
new ChallengeCommand(); new ChallengeCommand();
new HistoricCommand(); new HistoricCommand();
new CheckCommand(); new CheckCommand();
new RankedCommand();
new Broadcaster(); new Broadcaster();
}else{ }else{

Datei anzeigen

@ -1,67 +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.bungeecore.commands;
import de.steamwar.bungeecore.ArenaMode;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.sql.Elo;
import de.steamwar.bungeecore.sql.SteamwarUser;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.ArrayList;
import java.util.List;
public class RankCommand extends BasicCommand {
public RankCommand() {
super("rank", null);
}
@Override
public void execute(CommandSender sender, String[] args) {
if(!(sender instanceof ProxiedPlayer))
return;
ProxiedPlayer player = (ProxiedPlayer) sender;
Message.send("RANK_HEADER", player);
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
for(ArenaMode mode : ArenaMode.getAllModes()){
if(!mode.isRanked())
continue;
int elo = Elo.getElo(user.getId(), mode.getSchemType());
int placement = Elo.getPlacement(elo, mode.getSchemType());
if(placement == -1)
Message.send("RANK_UNPLACED", player, mode.getChatName());
else
Message.send("RANK_PLACED", player, mode.getChatName(), placement, elo);
}
}
@Override
public Iterable<String> onTabComplete(CommandSender commandSender, String[] args) {
if(args.length > 1)
return new ArrayList<>();
List<String> result = ArenaMode.getAllRankedChatNames();
result.removeIf(name -> !name.startsWith(args[0]));
return result;
}
}

Datei anzeigen

@ -1,216 +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.bungeecore.commands;
import de.steamwar.bungeecore.*;
import de.steamwar.bungeecore.sql.Elo;
import de.steamwar.bungeecore.sql.SteamwarUser;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class RankedCommand extends BasicCommand {
private static Map<ArenaMode, WaitingQueue> queues = new HashMap<>();
public RankedCommand() {
super("ranked", null);
for(ArenaMode mode : ArenaMode.getAllModes())
if(mode.isRanked())
queues.put(mode, new WaitingQueue(mode));
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), this::checkForGames, 1, 1, TimeUnit.SECONDS);
}
@Override
public void execute(CommandSender sender, String[] args) {
if(!(sender instanceof ProxiedPlayer)) {
return;
}
if(args.length < 1){
getModes(sender, "/ranked ");
return;
}
ArenaMode mode = FightCommand.getMode(sender, args[0]);
if(mode == null)
return;
else if(!mode.isRanked()){
Message.send("RANKED_NO_RANKED_MODE", sender);
return;
}
ProxiedPlayer player = (ProxiedPlayer) sender;
queues.get(mode).togglePlayer(player);
}
@Override
public Iterable<String> onTabComplete(CommandSender commandSender, String[] args) {
if(args.length > 1)
return new ArrayList<>();
List<String> result = ArenaMode.getAllRankedChatNames();
result.removeIf(name -> !name.startsWith(args[0]));
return result;
}
static void getModes(CommandSender sender, String precommand){
TextComponent start = new TextComponent();
TextComponent current = start;
for(ArenaMode mode : ArenaMode.getAllModes()){
if(mode.withoutChatName() || !mode.isRanked())
continue;
String command = precommand + mode.getChatName();
current.setBold(true);
current.setColor(ChatColor.GRAY);
current.setText(mode.getChatName() + " ");
current.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("§e" + command).create()));
current.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command));
if(current != start)
start.addExtra(current);
current = new TextComponent();
}
sender.sendMessage(start);
}
private void checkForGames(){
for(WaitingQueue queue : queues.values())
queue.checkForGames();
}
private static class WaitingQueue{
Set<WaitingPlayer> players = new HashSet<>();
private final ArenaMode mode;
private WaitingQueue(ArenaMode mode) {
this.mode = mode;
}
private void togglePlayer(ProxiedPlayer player){
for(WaitingPlayer wp : players){
if(wp.player == player){
Message.send("RANKED_QUEUE_LEFT", player);
players.remove(wp);
return;
}
}
Message.send("RANKED_QUEUE_JOINED", player);
Message.send("RANKED_QUEUE_HOW_TO_LEAVE", player);
players.add(new WaitingPlayer(player, mode.getSchemType()));
}
private void removeFromAll(ProxiedPlayer player){
for(WaitingQueue queue : queues.values()){
Iterator<WaitingPlayer> it = queue.players.iterator();
while(it.hasNext()){
WaitingPlayer wp = it.next();
if(wp.player == player){
it.remove();
break;
}
}
}
}
private void checkForGames(){
players.removeIf(wp -> !wp.doesStillWait());
Map<WaitingPlayer, WaitingPlayer> inRange = new HashMap<>();
//Find games
for(WaitingPlayer wp1 : players){
if(inRange.containsValue(wp1))
continue;
for(WaitingPlayer wp2 : players){
if(wp1 == wp2 || inRange.containsKey(wp2) || inRange.containsValue(wp2))
continue;
if(wp1.inRange(wp2))
inRange.putIfAbsent(wp1, wp2);
}
wp1.increment();
}
for(Map.Entry<WaitingPlayer, WaitingPlayer> entry : inRange.entrySet()){
WaitingPlayer wp1 = entry.getKey();
WaitingPlayer wp2 = entry.getValue();
Message.send("RANKED_ENEMY_SPOTTED", wp1.player);
Message.send("RANKED_ENEMY_SPOTTED", wp2.player);
removeFromAll(wp1.player);
removeFromAll(wp2.player);
Subserver arena = SubserverSystem.startArena(mode, mode.getRandomMap(), 0, 0, 0, 0, null, null, wp1.player.getUniqueId(), wp2.player.getUniqueId(), true);
arena.sendPlayer(wp1.player);
arena.sendPlayer(wp2.player);
Message.broadcast("RANKED_BROADCAST", "RANKED_BROADCAST_HOVER",
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), wp1.player.getName(), wp2.player.getName());
}
}
}
private static class WaitingPlayer{
private int currentRange;
private final int elo;
private final ProxiedPlayer player;
private WaitingPlayer(ProxiedPlayer player, String gameMode){
this.player = player;
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
elo = Elo.getElo(user.getId(), gameMode);
currentRange = 0;
}
private boolean inRange(WaitingPlayer player){
return Math.abs(elo - player.elo) <= this.currentRange;
}
private void increment(){
currentRange++;
}
private boolean doesStillWait(){
if(!player.isConnected())
return false;
Subserver subserver = Subserver.getSubserver(player);
if(subserver == null)
return true;
if(subserver.getType() == Servertype.ARENA){
Message.send("RANKED_QUEUE_LEFT", player);
return false;
}
return true;
}
}
}

Datei anzeigen

@ -36,4 +36,5 @@ public class PacketIdManager {
//0x2(X) Server Information System //0x2(X) Server Information System
public static final byte I_AM_A_LOBBY = 0x20; public static final byte I_AM_A_LOBBY = 0x20;
public static final byte FIGHT_INFO = 0x21; public static final byte FIGHT_INFO = 0x21;
public static final byte FIGHT_ENDS = 0x22;
} }

Datei anzeigen

@ -22,6 +22,7 @@ package de.steamwar.bungeecore.comms;
import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import de.steamwar.bungeecore.comms.handlers.*; import de.steamwar.bungeecore.comms.handlers.*;
import de.steamwar.bungeecore.comms.packets.FightEndsPacket;
import de.steamwar.bungeecore.listeners.BasicListener; import de.steamwar.bungeecore.listeners.BasicListener;
import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.api.event.PluginMessageEvent;
@ -59,5 +60,6 @@ public class SpigotReceiver extends BasicListener {
registerHandler(PacketIdManager.I_AM_A_LOBBY, new ImALobbyHandler()); registerHandler(PacketIdManager.I_AM_A_LOBBY, new ImALobbyHandler());
registerHandler(PacketIdManager.FIGHT_INFO, new FightInfoHandler()); registerHandler(PacketIdManager.FIGHT_INFO, new FightInfoHandler());
registerHandler(PacketIdManager.EXECUTE_COMMAND, new ExecuteCommandHandler()); registerHandler(PacketIdManager.EXECUTE_COMMAND, new ExecuteCommandHandler());
registerHandler(PacketIdManager.FIGHT_ENDS, new FightEndsHandler());
} }
} }

Datei anzeigen

@ -0,0 +1,34 @@
/*
* 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.bungeecore.comms.handlers;
import com.google.common.io.ByteArrayDataInput;
import de.steamwar.bungeecore.comms.SpigotHandler;
import de.steamwar.bungeecore.comms.packets.FightEndsPacket;
import net.md_5.bungee.api.config.ServerInfo;
public class FightEndsHandler implements SpigotHandler {
@Override
public void handle(ByteArrayDataInput in, ServerInfo info) {
FightEndsPacket fightEndsPacket = new FightEndsPacket(in);
}
}

Datei anzeigen

@ -0,0 +1,74 @@
/*
* 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.bungeecore.comms.packets;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import de.steamwar.bungeecore.comms.BungeePacket;
import de.steamwar.bungeecore.comms.PacketIdManager;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
@AllArgsConstructor
@Getter
public class FightEndsPacket extends BungeePacket {
private byte win;
private int blueSchem;
private int redSchem;
private List<Integer> bluePlayers;
private List<Integer> redPlayers;
public FightEndsPacket(ByteArrayDataInput byteArrayDataInput) {
win = byteArrayDataInput.readByte();
blueSchem = byteArrayDataInput.readInt();
redSchem = byteArrayDataInput.readInt();
int blueSize = byteArrayDataInput.readInt();
for (int i = 0; i < blueSize; i++) {
bluePlayers.add(byteArrayDataInput.readInt());
}
int redSize = byteArrayDataInput.readInt();
for (int i = 0; i < redSize; i++) {
redPlayers.add(byteArrayDataInput.readInt());
}
}
@Override
public int getId() {
return PacketIdManager.FIGHT_ENDS;
}
@Override
public void writeVars(ByteArrayDataOutput byteArrayDataOutput) {
byteArrayDataOutput.writeByte(win);
byteArrayDataOutput.writeInt(blueSchem);
byteArrayDataOutput.writeInt(redSchem);
byteArrayDataOutput.writeInt(bluePlayers.size());
for (int i : bluePlayers) {
byteArrayDataOutput.writeInt(i);
}
byteArrayDataOutput.writeInt(redPlayers.size());
for (int i : redPlayers) {
byteArrayDataOutput.writeInt(i);
}
}
}

Datei anzeigen

@ -21,24 +21,32 @@ package de.steamwar.bungeecore.sql;
public class Elo { public class Elo {
private static final Statement elo = new Statement("SELECT Elo FROM Elo WHERE UserID = ? AND GameMode = ?"); private static final Statement elo = new Statement("SELECT Elo FROM Elo WHERE UserID = ? AND GameMode = ? AND Season = ?");
private static final Statement place = new Statement("SELECT COUNT(*) AS Place FROM Elo WHERE GameMode = ? AND Elo > ?"); private static final Statement place = new Statement("SELECT COUNT(*) AS Place FROM Elo WHERE GameMode = ? AND Elo > ? AND Season = ?");
private Elo(){} private Elo(){}
public static int getElo(int userID, String gameMode){ public static int getElo(int userID, String gameMode){
return getElo(Season.getSeason(), userID, gameMode);
}
public static int getElo(int season, int userID, String gameMode){
return elo.select(rs -> { return elo.select(rs -> {
if(rs.next()) if(rs.next())
return rs.getInt("Elo"); return rs.getInt("Elo");
return 1000; return 1000;
}, userID, gameMode); }, userID, gameMode, season);
} }
public static int getPlacement(int elo, String gameMode){ public static int getPlacement(int elo, String gameMode){
return getPlacement(Season.getSeason(), elo, gameMode);
}
public static int getPlacement(int season, int elo, String gameMode){
return place.select(rs -> { return place.select(rs -> {
if(rs.next()) if(rs.next())
return rs.getInt("Place"); return rs.getInt("Place");
return -1; return -1;
}, gameMode, elo); }, gameMode, elo, season);
} }
} }

Datei anzeigen

@ -0,0 +1,49 @@
/*
* 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.bungeecore.sql;
import java.util.Calendar;
public class Season {
private Season() {}
public static int getSeason() {
Calendar calendar = Calendar.getInstance();
int yearIndex = calendar.get(Calendar.MONTH) / 3;
return (calendar.get(Calendar.YEAR) * 3 + yearIndex);
}
public static String convertSeasonToString(int season){
if (season == -1) return "";
int yearSeason = season % 3;
int year = (season - yearSeason) / 3;
return String.format("%d-%d", year, yearSeason);
}
public static int convertSeasonToNumber(String season){
if (season.isEmpty()) return -1;
String[] split = season.split("-");
try {
return Integer.parseInt(split[0]) * 3 + Integer.parseInt(split[1]);
} catch (NumberFormatException e) {
return -1;
}
}
}

Datei anzeigen

@ -301,20 +301,6 @@ POLL_NO_ANSWER=§cDas ist keine Antwortmöglichkeit!
POLL_ANSWER_REFRESH=§aDeine Antwort wurde aktualisiert. POLL_ANSWER_REFRESH=§aDeine Antwort wurde aktualisiert.
POLL_ANSWER_NEW=§aDeine Antwort wurde registriert. POLL_ANSWER_NEW=§aDeine Antwort wurde registriert.
#RankCommand
RANK_HEADER=§7§lPlatzierungen
RANK_UNPLACED=§7{0}§8: §eunplatziert
RANK_PLACED=§7{0}§8: §e{1}§8. §7mit §e{2} §7Elo§8.
#RankedCommand
RANKED_NO_RANKED_MODE=§cDieser Spielmodus ist nicht für Ranglistenspiele freigeschalten.
RANKED_QUEUE_JOINED=§aRanglistenspiel-Warteschlange betreten.
RANKED_QUEUE_HOW_TO_LEAVE=§7Wiederhole den Befehl zum Verlassen der Warteschlange.
RANKED_QUEUE_LEFT=§cRanglistenspiel-Warteschlange verlassen.
RANKED_ENEMY_SPOTTED=§eGegner gefunden! Ranglistenspiel startet.
RANKED_BROADCAST=§7{0}§8-§7Ranglistenspiel§8: §e{1} vs {2}
RANKED_BROADCAST_HOVER=§aZuschauen
#RCommand #RCommand
R_USAGE=§8/§7r §8[§eAntwort§8] R_USAGE=§8/§7r §8[§eAntwort§8]
R_NOTHING=§cDu hast bisher mit niemandem geschrieben! R_NOTHING=§cDu hast bisher mit niemandem geschrieben!