From dc26190aca85584ba12a0f75058e57b5c3ffca27 Mon Sep 17 00:00:00 2001 From: DroppingStar Date: Sat, 22 Jun 2024 01:16:27 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E7=9A=84=E6=B7=B7=E4=B9=B1=E6=83=85=E5=86=B5?= =?UTF-8?q?=E5=8F=91=E7=94=9F=20-=20=E7=8E=B0=E5=9C=A8welcomeMsg=E5=BE=88?= =?UTF-8?q?=E6=98=8E=E6=98=BE=E5=8F=AF=E4=BB=A5=E4=BD=BF=E7=94=A8=E4=BA=86?= =?UTF-8?q?=EF=BC=8C=E4=BD=A0=E5=8F=AF=E4=BB=A5=E4=BD=BF=E7=94=A8=E5=A6=82?= =?UTF-8?q?=E4=B8=8Btag=E6=9D=A5=E8=87=AA=E5=AE=9A=E4=B9=89=E4=BD=A0?= =?UTF-8?q?=E7=9A=84=E6=AC=A2=E8=BF=8E=E4=BF=A1=E6=81=AF=EF=BC=9A=20{playe?= =?UTF-8?q?rName}:=20=E7=8E=A9=E5=AE=B6=E5=90=8D=E7=A7=B0=20{simpleUUID}:?= =?UTF-8?q?=20=E7=8E=A9=E5=AE=B6UUID=E5=89=8D=E5=85=AB=E4=BD=8D=20{package?= =?UTF-8?q?Name}:=20=E7=8E=A9=E5=AE=B6=E6=B8=B8=E6=88=8F=E7=9A=84=E5=8C=85?= =?UTF-8?q?=E5=90=8D=20{versionCode}:=20=E7=8E=A9=E5=AE=B6=E7=9A=84?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E7=89=88=E6=9C=AC=20-=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BE=9D=E8=B5=96=E5=B9=B6=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=20yaml=20=E6=9C=89=E5=85=B3=E5=86=85=E5=AE=B9=20-=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=90=AF=E5=8A=A8=E6=97=B6=E8=AF=BB=E5=8F=96lang?= =?UTF-8?q?=E6=97=B6=E9=80=A0=E6=88=90=E7=9A=84=E5=90=AF=E5=8A=A8=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E9=97=AE=E9=A2=98=20-=20=E4=BF=AE=E5=A4=8D=20TestPlug?= =?UTF-8?q?in=20=E4=B8=AD=E7=9A=84=E5=8D=95=E4=BD=8D=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=E7=9A=84=20bug=20-=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=B8=B8=E6=88=8F=E5=90=8C=E6=AD=A5=E5=88=B0?= =?UTF-8?q?=E9=87=8D=E8=BF=9E=E6=B8=B8=E6=88=8F=E7=9A=84=E7=8E=A9=E5=AE=B6?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E6=95=B4=E7=9B=98=E6=B8=B8=E6=88=8F=E9=87=8D?= =?UTF-8?q?=E5=BC=80=E7=9A=84=E9=97=AE=E9=A2=98=20-=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=88=BF=E9=97=B4=E7=8E=A9=E5=AE=B6=E5=9C=B0=E5=9B=BE=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E7=9A=84=E9=94=99=E4=B9=B1=E9=97=AE=E9=A2=98=20-=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=88=BF=E9=97=B4=E7=8E=A9=E5=AE=B6=E5=8F=91?= =?UTF-8?q?=E9=80=81=20info=20=E4=B8=8D=E5=90=8C=E6=AD=A5=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E6=97=B6=E8=87=AA=E5=8A=A8=E8=BF=9B=E8=A1=8C=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E7=9A=84=E5=8A=9F=E8=83=BD=20-=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=85=B1=E4=BA=AB=E6=8E=A7=E5=88=B6=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=8E=A9=E5=AE=B6=E7=A6=BB=E7=BA=BF=E5=90=AF?= =?UTF-8?q?=E7=94=A8=E5=85=B1=E4=BA=AB=E6=8E=A7=E5=88=B6=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=20-=20=E5=A2=9E=E5=8A=A0=20API:=20NetworkPlayer.sendTeamMessag?= =?UTF-8?q?e(String=20msg)=20-=20=E8=B0=83=E6=95=B4=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E7=BA=A7=E5=88=AB=E8=87=B3=20trace=20?= =?UTF-8?q?=E4=BB=A5=E7=AE=80=E5=8C=96=E8=BE=93=E5=87=BA=20-=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20isDebug=20=E4=B8=BA=20true=20=E6=97=B6=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E4=B8=8D=E8=BE=93=E5=87=BA=20debug=20=E7=BA=A7?= =?UTF-8?q?=E5=88=AB=E6=97=A5=E5=BF=97=E7=9A=84=E9=97=AE=E9=A2=98=20-=20Fi?= =?UTF-8?q?xed=20the=20sync=20game=20problem.=20-=20welcomeMsg=20in=20rukk?= =?UTF-8?q?it.yml=20can=20be=20used,=20you=20can=20use=20this=20following?= =?UTF-8?q?=20tags=20to=20customize=20your=20server's=20welcome=20message.?= =?UTF-8?q?=20=20{playerName},=20{simpleUUID}(first=208=20degit=20of=20pla?= =?UTF-8?q?yer's=20uuid),=20{packageName}(Player=20client's=20package=20na?= =?UTF-8?q?me),=20{versionCode}(Player=20client's=20version=20code)=20=20-?= =?UTF-8?q?=20updated=20dependence,=20and=20ported=20the=20new=20version?= =?UTF-8?q?=20of=20SnakeYaml.=20=20-=20Fixed=20when=20starting=20the=20ser?= =?UTF-8?q?ver,=20server=20will=20be=20broken=20due=20to=20the=20bad=20lan?= =?UTF-8?q?g=20format=20in=20rukkit.yml.=20=20-=20Fixed=20the=20sharing=20?= =?UTF-8?q?control=20not=20working=20problem.=20=20-=20Fixed=20the=20confl?= =?UTF-8?q?ict=20round=20info=20between=20the=20room.=20=20-=20Fixed=20whe?= =?UTF-8?q?n=20a=20player=20reconnected=20the=20game,=20the=20game=20have?= =?UTF-8?q?=20the=20possibility=20the=20sync=20with=20the=20reconnecting?= =?UTF-8?q?=20player's=20save,=20which=20lead=20to=20restart=20the=20game.?= =?UTF-8?q?=20=20-=20Fixed=20the=20summon=20command=20bugs.=20=20-=20Added?= =?UTF-8?q?=20the=20ability=20when=20player=20send=20a=20info,=20the=20ser?= =?UTF-8?q?ver=20will=20start=20sync=20automatically.=20=20-=20Add=20API?= =?UTF-8?q?=20NetworkPlayer.sendTeamMessage=20=20-=20Changed=20some=20log?= =?UTF-8?q?=20level=20to=20trace=20=20-=20Fixed=20when=20isDebug=20=3D=20t?= =?UTF-8?q?rue,=20the=20server=20would=20not=20enable=20the=20debug=20log.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/cn/rukkit/Rukkit.java | 24 +++- src/main/java/cn/rukkit/RukkitLauncher.java | 3 +- .../command/completer/PlayerCompleter.java | 13 +- .../java/cn/rukkit/config/BaseConfig.java | 3 +- .../java/cn/rukkit/config/RukkitConfig.java | 6 +- .../java/cn/rukkit/game/NetworkPlayer.java | 36 ++++-- .../java/cn/rukkit/game/PlayerManager.java | 3 +- .../cn/rukkit/network/ConnectionHandler.java | 122 ++++++++++-------- .../java/cn/rukkit/network/NetworkRoom.java | 11 +- .../rukkit/network/RoomConnectionManager.java | 2 +- .../java/cn/rukkit/network/packet/Packet.java | 18 +-- .../java/cn/rukkit/plugin/PluginConfig.java | 1 + .../java/cn/rukkit/plugin/PluginManager.java | 2 +- .../java/cn/rukkit/plugin/RukkitPlugin.java | 3 +- .../cn/rukkit/plugin/internal/BasePlugin.java | 10 ++ .../rukkit/plugin/internal/CommandPlugin.java | 29 +++-- .../plugin/internal/ServerCommandPlugin.java | 9 +- .../cn/rukkit/plugin/internal/TestPlugin.java | 2 +- src/main/java/cn/rukkit/util/LangUtil.java | 5 + src/main/java/cn/rukkit/util/Vote.java | 4 +- src/main/resources/i18n/messages.properties | 7 +- .../resources/i18n/messages_en_US.properties | 6 +- .../resources/i18n/messages_zh_CN.properties | 9 +- 23 files changed, 216 insertions(+), 112 deletions(-) diff --git a/src/main/java/cn/rukkit/Rukkit.java b/src/main/java/cn/rukkit/Rukkit.java index 342bac3..f4139c8 100644 --- a/src/main/java/cn/rukkit/Rukkit.java +++ b/src/main/java/cn/rukkit/Rukkit.java @@ -8,6 +8,7 @@ */ package cn.rukkit; +import ch.qos.logback.classic.Level; import cn.rukkit.command.*; import cn.rukkit.config.*; import cn.rukkit.game.NetworkPlayer; @@ -23,13 +24,14 @@ import cn.rukkit.plugin.internal.*; import cn.rukkit.service.*; import cn.rukkit.game.SaveManager; +import org.yaml.snakeyaml.nodes.Tag; import java.util.Locale; import java.util.UUID; public class Rukkit { private static boolean isStarted = false; - public static final String RUKKIT_VERSION = "0.9.3-dev"; + public static final String RUKKIT_VERSION = "0.9.4-dev"; public static final int SUPPORT_GAME_VERSION = 176; private static final Logger log = LoggerFactory.getLogger(Rukkit.class); private static RoundConfig round; @@ -157,7 +159,7 @@ public static void loadRukkitConfig() throws IOException { FileWriter writer = new FileWriter(confFile); RukkitConfig conf = new RukkitConfig(); conf.UUID = UUID.randomUUID().toString(); - writer.write(yaml.dumpAs(conf, null, DumperOptions.FlowStyle.BLOCK)); + writer.write(yaml.dumpAs(conf, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); writer.flush(); writer.close(); } @@ -175,7 +177,7 @@ public static final void loadRoundConfig() throws IOException { confFile.delete(); confFile.createNewFile(); FileWriter writer = new FileWriter(confFile); - writer.write(yaml.dumpAs(new RoundConfig(), null, DumperOptions.FlowStyle.BLOCK)); + writer.write(yaml.dumpAs(new RoundConfig(), Tag.MAP, DumperOptions.FlowStyle.BLOCK)); writer.flush(); writer.close(); } @@ -192,7 +194,7 @@ public static final T getConfig(String path, Class cls) throws FileNotFou confFile.delete(); confFile.createNewFile(); FileWriter writer = new FileWriter(confFile); - writer.write(yaml.dumpAs(cls, null, DumperOptions.FlowStyle.BLOCK)); + writer.write(yaml.dumpAs(cls, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); writer.flush(); writer.close(); } @@ -244,10 +246,22 @@ public static final void startServer() throws IOException, InterruptedException log.info("load::RukkitConfig..."); // 加载配置文件 loadRukkitConfig(); + if (config.isDebug) { + log.info("debug::Change log level to debug..."); + ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) org.slf4j.LoggerFactory + .getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); + root.setLevel(Level.DEBUG); + + } log.info("load::RoundConfig..."); loadRoundConfig(); log.info("load::Language..."); // 加载语言文件 - LangUtil.lc = new Locale(getConfig().lang.split("_")[0], getConfig().lang.split("_")[1]); + String[] lang_format = getConfig().lang.split("_"); + if (lang_format.length < 2) { + log.warn("Invalid Language configuration {} detected, we will use system default language. Please check your rukkit.yml.", getConfig().lang); + } else { + LangUtil.lc = new Locale(lang_format[0], lang_format[1]); + } log.info("Current Language: {}", LangUtil.lc); //init SaveManager. log.info("load::DefaultSaveData..."); // 加载保存文件 diff --git a/src/main/java/cn/rukkit/RukkitLauncher.java b/src/main/java/cn/rukkit/RukkitLauncher.java index 97f7a21..c083570 100644 --- a/src/main/java/cn/rukkit/RukkitLauncher.java +++ b/src/main/java/cn/rukkit/RukkitLauncher.java @@ -53,13 +53,14 @@ public static void main(String args[]){ Rukkit.startServer(); while (isTerminalRunning) { try { - String str = lineReader.readLine(PATTERN); + Thread.sleep(1); // 不知道为什么反正要这个东西 if (Rukkit.getCommandManager() == null) continue; if (Rukkit.isStarted()) { serverCommandCompleter.setCommandCompleteVars(Rukkit.getCommandManager().getLoadedServerCommandStringList()); } else { continue; } + String str = lineReader.readLine(PATTERN); Rukkit.getCommandManager().executeServerCommand(str); } catch (UserInterruptException e) { diff --git a/src/main/java/cn/rukkit/command/completer/PlayerCompleter.java b/src/main/java/cn/rukkit/command/completer/PlayerCompleter.java index a0ea252..6868819 100644 --- a/src/main/java/cn/rukkit/command/completer/PlayerCompleter.java +++ b/src/main/java/cn/rukkit/command/completer/PlayerCompleter.java @@ -9,8 +9,19 @@ package cn.rukkit.command.completer; +import org.jline.reader.Candidate; +import org.jline.reader.Completer; +import org.jline.reader.LineReader; +import org.jline.reader.ParsedLine; import org.jline.reader.impl.completer.StringsCompleter; +import java.util.List; + public class PlayerCompleter extends StringsCompleter { - + Completer completer; + + @Override + public void complete(LineReader reader, ParsedLine commandLine, List candidates) { + StringsCompleter stringsCompleter = new StringsCompleter(); + } } diff --git a/src/main/java/cn/rukkit/config/BaseConfig.java b/src/main/java/cn/rukkit/config/BaseConfig.java index 6573df4..191626f 100644 --- a/src/main/java/cn/rukkit/config/BaseConfig.java +++ b/src/main/java/cn/rukkit/config/BaseConfig.java @@ -14,6 +14,7 @@ import org.yaml.snakeyaml.*; //import java.util.logging.*; import org.slf4j.*; +import org.yaml.snakeyaml.nodes.Tag; public abstract class BaseConfig { @@ -32,7 +33,7 @@ public BaseConfig loadConfig() throws IllegalAccessException, InstantiationExcep confFile.createNewFile(); BaseConfig cfg = this.getClass().newInstance(); FileWriter writer = new FileWriter(confFile); - writer.write(new Yaml().dumpAs(cfg, null, DumperOptions.FlowStyle.BLOCK)); + writer.write(new Yaml().dumpAs(cfg, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); writer.flush(); writer.close(); return cfg; diff --git a/src/main/java/cn/rukkit/config/RukkitConfig.java b/src/main/java/cn/rukkit/config/RukkitConfig.java index be35795..3a89e96 100644 --- a/src/main/java/cn/rukkit/config/RukkitConfig.java +++ b/src/main/java/cn/rukkit/config/RukkitConfig.java @@ -14,7 +14,7 @@ public class RukkitConfig extends BaseConfig { public String serverUser = "RUKKIT"; - public String welcomeMsg = "Welcome to Rukkit server, {user}!"; + public String welcomeMsg = "Welcome to Rukkit server, {playerName}!"; public String serverMotd = "My Rukkit server"; public int serverPort = 5123; public int maxPlayer = 10; @@ -30,6 +30,10 @@ public class RukkitConfig extends BaseConfig public String lang = Locale.getDefault().toString(); //max threads in manager.Default = 8; public int threadPoolCount = 8; + // max unit in per player 单玩家最大单位 + public int maxUnitsPerPlayer = 250; + // using question system to vote 投票系统使用提示框模式实现 + // public boolean usingPopupInVote = false; //Ping packet receive timeout.default = 8000 (ms) public int pingTimeout = 8000; diff --git a/src/main/java/cn/rukkit/game/NetworkPlayer.java b/src/main/java/cn/rukkit/game/NetworkPlayer.java index 1750e3c..b7a3699 100644 --- a/src/main/java/cn/rukkit/game/NetworkPlayer.java +++ b/src/main/java/cn/rukkit/game/NetworkPlayer.java @@ -11,11 +11,14 @@ import cn.rukkit.*; import cn.rukkit.network.*; import cn.rukkit.network.packet.Packet; +import cn.rukkit.util.LangUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.nodes.Tag; import java.io.*; import java.nio.charset.StandardCharsets; @@ -47,6 +50,9 @@ public class NetworkPlayer public boolean isSharingControl = false; public boolean isSurrounded = false; + public boolean isDisconnected = false; + + public boolean isAfk = false; private NetworkRoom room; public NetworkPlayer(RoomConnection connection) { @@ -126,10 +132,10 @@ public void putExtraData(String key, Object value) { * Save player data. */ public void savePlayerData() { - Yaml yaml = new Yaml(new Constructor(NetworkPlayerData.class)); + Yaml yaml = new Yaml(new Constructor(NetworkPlayerData.class, new LoaderOptions())); try { FileWriter writer = new FileWriter(Rukkit.getEnvPath() + "/data/player/" + uuid + ".yaml"); - writer.write(yaml.dumpAs(data, null, DumperOptions.FlowStyle.BLOCK)); + writer.write(yaml.dumpAs(data, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); writer.flush(); writer.close(); } catch (FileNotFoundException e) { @@ -143,8 +149,8 @@ public void writePlayer(DataOutputStream stream, boolean simpleMode) throws IOEx if (simpleMode) { stream.writeByte(0); stream.writeInt(ping); - stream.writeBoolean(true); - stream.writeBoolean(true); + stream.writeBoolean(isSharingControl); + stream.writeBoolean(isDisconnected || isAfk); } else { //玩家位置 stream.writeByte(playerIndex); @@ -238,6 +244,16 @@ public void updateServerInfo() { } catch (IOException e) {} } + public void sendTeamMessage(String message) { + for (RoomConnection conn: room.connectionManager.getConnections()) { + if (team == conn.player.team) { + conn.sendMessage(name, + LangUtil.getString("chat.teamMsg") + " " + message, + playerIndex); + } + } + } + @Override public String toString() { return "NetworkPlayer{" + @@ -271,22 +287,22 @@ public static final void initPlayerDataDir() { public void loadPlayerData() { Logger log = LoggerFactory.getLogger("PlayerData"); - log.info("Load player infomation."); - Yaml yaml = new Yaml(new Constructor(NetworkPlayerData.class)); + log.debug("Load player infomation."); + Yaml yaml = new Yaml(new Constructor(NetworkPlayerData.class, new LoaderOptions())); File dataFile = new File(Rukkit.getEnvPath() + "/data/player/" + uuid + ".yaml"); try { if (dataFile.exists()) { - log.info("Player exists.Loading..."); + log.debug("Player exists.Loading..."); data = yaml.load(new FileInputStream(dataFile)); data.lastUsedName = name; data.lastConnectedTime = new Date().toString(); data.lastConnectedAddress = connection.handler.ctx.channel().remoteAddress().toString(); Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dataFile), StandardCharsets.UTF_8)); - writer.write(yaml.dumpAs(data, null, DumperOptions.FlowStyle.BLOCK)); + writer.write(yaml.dumpAs(data, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); writer.flush(); writer.close(); } else { - log.info("New player.Creating file..."); + log.info("New player.Creating data file..."); dataFile.createNewFile(); data = new NetworkPlayerData(); data.uuid = uuid; @@ -294,7 +310,7 @@ public void loadPlayerData() { data.lastConnectedTime = new Date().toString(); data.lastConnectedAddress = connection.handler.ctx.channel().remoteAddress().toString(); Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dataFile), StandardCharsets.UTF_8)); - writer.write(yaml.dumpAs(data, null, DumperOptions.FlowStyle.BLOCK)); + writer.write(yaml.dumpAs(data, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); writer.flush(); writer.close(); } diff --git a/src/main/java/cn/rukkit/game/PlayerManager.java b/src/main/java/cn/rukkit/game/PlayerManager.java index ee1f740..5c7b6ad 100644 --- a/src/main/java/cn/rukkit/game/PlayerManager.java +++ b/src/main/java/cn/rukkit/game/PlayerManager.java @@ -29,7 +29,7 @@ public PlayerManager(NetworkRoom room, int maxPlayer) { reset(); } - private NetworkPlayer[] players; + private volatile NetworkPlayer[] players; //private static Player[] inGamePlayers = new Player[ServerProperties.maxPlayer]; /** @@ -80,6 +80,7 @@ public void remove(int index){ // } if(currentRoom.isGaming()){ players[index].ping = -1; + players[index].isDisconnected = true; return; } players[index] = new NetworkPlayer(); diff --git a/src/main/java/cn/rukkit/network/ConnectionHandler.java b/src/main/java/cn/rukkit/network/ConnectionHandler.java index ca80922..7a7780e 100644 --- a/src/main/java/cn/rukkit/network/ConnectionHandler.java +++ b/src/main/java/cn/rukkit/network/ConnectionHandler.java @@ -73,7 +73,9 @@ public void channelInactive(ChannelHandlerContext ctx) throws Exception { conn.stopPingTask(); conn.stopTeamTask(); } else { - log.warn("There is a unexpected connection at connection {}.", ctx.channel().remoteAddress()); + if (!(ctx.channel().remoteAddress().toString().contains("18.216.139.119") || ctx.channel().remoteAddress().toString().contains("192.241.156.189"))) { // Whitelist of official server + log.warn("There is a unexpected connection at connection {}.", ctx.channel().remoteAddress()); + } } } @@ -91,21 +93,23 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception break; case Packet.PACKET_PLAYER_INFO: String packageName = in.readString(); - log.info("Ints:" + in.readInt()); + log.debug("Ints:" + in.readInt()); int gameVersionCode = in.readInt(); in.readInt(); String playerName = in.readString(); - in.readByte(); - in.readString(); - // 玩家固有的uuid,前提是verifyCode不改变 + // 服务器密码判定 + in.readByte(); // 其实是 boolean + // 如果上面那个为 true,则接下来读 String 做密码 + in.readString(); // packageName + // 玩家固有的uuid,前提是verifyCode不改变 (在rw内叫clientKey) String uuid = in.readString(); // 核心单位检查,用于判断玩家是否对客户端进行修改 // 1.14:1198432602 // 1.15:678359601 int coreUnitCheck = in.readInt(); String verifyResult = in.readString(); - log.info(String.format("Got Player(package=%s, version=%d, name=%s, uuid=%s, verify=%s, coreUnit=%d", - packageName, gameVersionCode, playerName, uuid, verifyResult, coreUnitCheck)); + log.debug(String.format("Got Player(package=%s, version=%d, name=%s, uuid=%s, coreUnit=%d", + packageName, gameVersionCode, playerName, uuid, coreUnitCheck)); // 获取当前的可用房间 NetworkRoom room = Rukkit.getRoomManager().getAvailableRoom(); @@ -117,6 +121,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception if (Rukkit.getConfig().syncEnabled) { // 获取上次断线时的断线房间 currentRoom = targetPlayer.getRoom(); + log.info("Found offline room {}", currentRoom.toString()); } else { currentRoom = room; } @@ -124,6 +129,12 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception currentRoom = room; } + // 无可用房间,踢出 + if (currentRoom == null) { + ctx.writeAndFlush(Packet.kick(LangUtil.getString("rukkit.gameFull"))); + return; + } + if (!currentRoom.isGaming() && targetPlayer != null) { // 如果 room 不在游戏,说明该uuid玩家发起了重复连接 log.info("Dup player {} (UUID={}) joined!", playerName, uuid); if (Rukkit.getConfig().isDebug) { @@ -152,12 +163,12 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception } // 检查房主 - if (room.connectionManager.size() <= 0) { + if (currentRoom.connectionManager.size() <= 0) { conn.sendServerMessage(LangUtil.getString("rukkit.playerGotAdmin")); conn.player.isAdmin = true; - ctx.writeAndFlush(Packet.serverInfo(room.config, true)); + ctx.writeAndFlush(Packet.serverInfo(currentRoom.config, true)); } else { - ctx.writeAndFlush(Packet.serverInfo(room.config)); + ctx.writeAndFlush(Packet.serverInfo(currentRoom.config)); } // 当前房间是否在游戏 @@ -174,9 +185,10 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception // Sync game conn.handler.ctx.writeAndFlush(Packet.startGame()); // conn.handler.ctx.writeAndFlush(Packet.sendSave(currentRoom, Rukkit.getDefaultSave().arr, false)); - room.syncGame(); + currentRoom.syncGame(); + conn.player.isDisconnected = false; - PlayerJoinEvent.getListenerList().callListeners(new PlayerJoinEvent(conn.player)); + // PlayerJoinEvent.getListenerList().callListeners(new PlayerJoinEvent(conn.player)); PlayerReconnectEvent.getListenerList().callListeners(new PlayerReconnectEvent(conn.player)); } else { ctx.writeAndFlush(p.kick(LangUtil.getString("rukkit.gameStarted"))); @@ -187,12 +199,21 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception Rukkit.getGlobalConnectionManager().add(conn); //Adding into RoomConnectionManager. if (targetPlayer == null) { - room.connectionManager.add(conn); + currentRoom.connectionManager.add(conn); } - conn.sendServerMessage("Hello, you are in room #" + currentRoom.roomId); //load player Data. - conn.player.loadPlayerData(); + try { + conn.player.loadPlayerData(); + } catch (Exception e) { + log.warn("Player {} data load failed!", playerName); + } + conn.sendServerMessage(LangUtil.getFormatString("rukkit.room", currentRoom.roomId)); + conn.sendServerMessage(Rukkit.getConfig().welcomeMsg + .replace("{playerName}", playerName) + .replace("{simpleUUID}", uuid.substring(0, 7)) + .replace("{packageName}", packageName) + .replace("{versionCode}", String.valueOf(gameVersionCode))); if (targetPlayer == null) { conn.startPingTask(); @@ -229,7 +250,8 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception //log.debug(str.readByte()); index = str.readByte(); out.writeByte(index); - log.debug("" + index); + log.debug("-- Command Recording --"); + log.debug("teamIndex=" + index); //是否为BasicAction if (str.readBoolean()) { @@ -248,7 +270,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception targetUnit = str.readString(); out.writeString(targetUnit); //((BuildAction)act).targetUnit = unit; - log.info("Custom=" + targetUnit); + log.debug("Custom=" + targetUnit); //sendPacket(ctx, new Packet().chat("Debug", "(External)You are building by builder:" + targetUnit, -1)); } @@ -279,12 +301,12 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception boolean bool1 = str.readBoolean(); boolean bool2 = str.readBoolean(); boolean bool3 = str.readBoolean(); - log.debug("Byte1=" + byte1); - log.debug("Float1=" + float1); - log.debug("Float2=" + float2); - log.debug("Boolean1=" + bool1); - log.debug("Boolean2=" + bool2); - log.debug("Boolean3=" + bool3); + log.trace("Byte1=" + byte1); + log.trace("Float1=" + float1); + log.trace("Float2=" + float2); + log.trace("Boolean1=" + bool1); + log.trace("Boolean2=" + bool2); + log.trace("Boolean3=" + bool3); out.writeByte(byte1); out.writeFloat(float1); out.writeFloat(float2); @@ -312,15 +334,15 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception out.writeBoolean(false); } // - log.debug("CommandBlock ended."); + log.trace("CommandBlock ended."); boolean bool4,isCancel; bool4 = str.readBoolean(); // 未知 isCancel = str.readBoolean(); - log.debug("Boolean4=" + bool4); + log.trace("Boolean4=" + bool4); //是否为取消操作 - log.debug("Boolean5=" + isCancel); + log.debug("isCancel=" + isCancel); out.writeBoolean(bool4); out.writeBoolean(isCancel); @@ -335,12 +357,12 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception // 疑似和核弹等目标发射有关,设置集结点 if (str.readBoolean()) { out.writeBoolean(true); - log.debug("A readBoolean is true."); + log.trace("A readBoolean is true."); float f3,f4; f3 = str.readFloat(); f4 = str.readFloat(); - log.debug("Float3=" + f3); - log.debug("Float4=" + f4); + log.trace("Float3=" + f3); + log.trace("Float4=" + f4); out.writeFloat(f3); out.writeFloat(f4); } else { @@ -349,7 +371,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception //未知 boolean bool6 = str.readBoolean(); - log.debug("Boolean6=" + bool6); + log.trace("Boolean6=" + bool6); //批量执行单位 int t = str.readInt(); @@ -367,9 +389,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception // 如果为True, 则为预执行命令 if (str.readBoolean()) { out.writeBoolean(true); - log.debug("A readBoolean is true."); + log.trace("A readBoolean is true."); byte2 = str.readByte(); //玩家 - log.debug("Byte2=" + byte2); + log.trace("Byte2=" + byte2); out.writeByte(byte2); } else { out.writeBoolean(false); @@ -380,12 +402,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception float pingY = 0; if (str.readBoolean()) { out.writeBoolean(true); - log.debug("Its a ping packet."); + log.trace("Its a ping packet."); //float f5,f6; pingX = str.readFloat(); pingY = str.readFloat(); - log.debug("PingX=" + pingX); - log.debug("PingX=" + pingY); + log.debug("PingX={} , PingY={}", pingX, pingY); out.writeFloat(pingX); out.writeFloat(pingY); } else { @@ -414,17 +435,17 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception // 为true时,单位完成除建造和修复外的所有路径行动 boolean bool7 = str.readBoolean(); - log.debug("Boolean7=" + bool7); + log.trace("Boolean7=" + bool7); out.writeBoolean(bool7); - // 能否进行玩家控制的关键代码,填写0即可。 + // 能否进行玩家控制的关键代码,填写32767即可。 short short1 = str.readShort(); - log.debug("Short1=" + short1); - out.stream.writeShort(0); + log.trace("Short1=" + short1); + out.stream.writeShort(32767); // SystemAction 比较危险,可以默认舍弃 if (str.readBoolean()) { - log.debug("A readBoolean is true."); + log.trace("A readBoolean is true."); out.writeBoolean(true); str.readByte(); out.writeByte(0); @@ -433,7 +454,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception f1 = str.readFloat(); f2 = str.readFloat(); i1 = str.readInt(); - log.debug("{}, {}, {}", f1, f2, i1); + log.trace("{}, {}, {}", f1, f2, i1); out.writeFloat(f1); out.writeFloat(f2); out.writeInt(i1); @@ -441,10 +462,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception out.writeBoolean(false); } - StringBuffer buf = new StringBuffer("Move units count: "); int movementUnitCount = str.readInt(); out.writeInt(movementUnitCount); - buf.append(movementUnitCount + " Unitids: "); + log.debug("count={}", movementUnitCount); for (int i = 0;i < movementUnitCount;i++) { float sx, sy, ex, ey; long unitid = str.readLong(); @@ -457,20 +477,12 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception out.writeFloat(sy); out.writeFloat(ex); out.writeFloat(ey); - log.debug("unitid:" + unitid); - buf.append(unitid + " "); - log.debug("startx:" + sx); - log.debug("starty:" + sy); - log.debug("endx" + ex); - log.debug("endy" + ey); //当前时间刻 int timestamp = str.readInt(); - log.debug("" + timestamp); out.writeInt(timestamp); //单位类型(1陆,潜艇,跨悬崖,跨悬崖跨水,悬浮5) UnitType u = (UnitType) str.readEnum(UnitType.class); - buf.append("(" + u + ") "); - log.debug(u.toString()); + log.debug("id={} startPos=({}, {}), endPos=({}, {}), startStamp={}, unitType={}", unitid, sx, sy, ex, ey, timestamp, u); out.writeEnum(u); // Path 有关内容 @@ -492,7 +504,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception short unity = ins.readShort(); outstr.stream.writeShort(unitx); outstr.stream.writeShort(unity); - log.debug("Start x:" + unitx + ", Start y:" + unity); + log.trace("Start x:" + unitx + ", Start y:" + unity); for (int i2 = 1;i2 < pathCount;i2++) { // PathSize int len = ins.readByte(); @@ -523,10 +535,10 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception out.writeBoolean(false); } } - log.debug(buf.toString()); boolean bool = str.readBoolean(); out.writeBoolean(bool); + log.debug("-- Command recording end --"); // byte[] byt = new byte[str.stream.available()]; // str.stream.read(byt); @@ -545,7 +557,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception } break; case Packet.PACKET_RANDY: - conn.sendServerMessage(String.format("Player '%s' is randy.", conn.player.name)); + currentRoom.connectionManager.broadcastServerMessage(String.format("Player '%s' is randy.", conn.player.name)); break; case Packet.PACKET_SYNC: in.readByte(); diff --git a/src/main/java/cn/rukkit/network/NetworkRoom.java b/src/main/java/cn/rukkit/network/NetworkRoom.java index faddc07..cdcd68c 100644 --- a/src/main/java/cn/rukkit/network/NetworkRoom.java +++ b/src/main/java/cn/rukkit/network/NetworkRoom.java @@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; +import java.text.MessageFormat; import java.util.LinkedList; import java.util.concurrent.ScheduledFuture; @@ -43,6 +44,12 @@ public class NetworkRoom { public Vote vote; + @Override + public String toString() { + return MessageFormat.format("NetworkRoom [id = {0}, isGaming = {1}, isPaused = {2}, currentStep = {3}, stepRate = {4}]", + roomId, isGaming, isPaused, currentStep, stepRate); + } + public NetworkRoom(int id) { // 指定房间id roomId = id; @@ -268,7 +275,7 @@ public void startGame() { for (NetworkPlayer p:playerManager.getPlayerArray()) { try { p.isNull(); - p.isSharingControl = true; + p.isSharingControl = false; } catch (NullPointerException ignored) {continue;} } } @@ -306,7 +313,7 @@ public void changeMapWhileRunning(String mapName, int type) { for (NetworkPlayer p:playerManager.getPlayerArray()) { try { p.isNull(); - p.isSharingControl = true; + // p.isSharingControl = true; } catch (NullPointerException ignored) {continue;} } } diff --git a/src/main/java/cn/rukkit/network/RoomConnectionManager.java b/src/main/java/cn/rukkit/network/RoomConnectionManager.java index bf1c49c..fc5dc26 100644 --- a/src/main/java/cn/rukkit/network/RoomConnectionManager.java +++ b/src/main/java/cn/rukkit/network/RoomConnectionManager.java @@ -28,7 +28,7 @@ public class RoomConnectionManager { private final NetworkRoom room; - List connections = new ArrayList(); + volatile List connections = new ArrayList(); private ChannelGroup CHANNEL_GROUP; private PlayerManager playerManager; diff --git a/src/main/java/cn/rukkit/network/packet/Packet.java b/src/main/java/cn/rukkit/network/packet/Packet.java index a7b5cdf..bc8929f 100644 --- a/src/main/java/cn/rukkit/network/packet/Packet.java +++ b/src/main/java/cn/rukkit/network/packet/Packet.java @@ -182,24 +182,24 @@ public static Packet serverInfo(RoundConfig config, boolean isAdmin, ArrayList T getConfig(File file, Class cls) throws FileNotFoundExcepti public final void saveConfig(File file, Object cls) throws IOException { Yaml yaml = new Yaml(); FileWriter writer = new FileWriter(file); - writer.write(yaml.dumpAs(cls, null, DumperOptions.FlowStyle.BLOCK)); + writer.write(yaml.dumpAs(cls, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); writer.flush(); writer.close(); } diff --git a/src/main/java/cn/rukkit/plugin/internal/BasePlugin.java b/src/main/java/cn/rukkit/plugin/internal/BasePlugin.java index f7425ad..d857118 100644 --- a/src/main/java/cn/rukkit/plugin/internal/BasePlugin.java +++ b/src/main/java/cn/rukkit/plugin/internal/BasePlugin.java @@ -19,6 +19,7 @@ import cn.rukkit.event.player.PlayerChatEvent; import cn.rukkit.event.player.PlayerJoinEvent; import cn.rukkit.event.player.PlayerLeftEvent; +import cn.rukkit.event.player.PlayerReconnectEvent; import cn.rukkit.network.RoomConnection; import cn.rukkit.plugin.PluginConfig; import cn.rukkit.util.LangUtil; @@ -41,6 +42,9 @@ public void onPlayerJoinTip(PlayerJoinEvent event) { @EventHandler public void onPlayerLeaveTip(PlayerLeftEvent event) { event.getPlayer().getRoom().connectionManager.broadcastServerMessage(MessageFormat.format(LangUtil.getString("rukkit.playerLeft"), event.getPlayer().name)); + if (event.getPlayer().getRoom().isGaming()) { + event.getPlayer().sendTeamMessage(LangUtil.getString("rukkit.playerSharingControlDueDisconnected")); + } LoggerFactory.getLogger("Room #" + event.getPlayer().getRoom().roomId).info("Player {} left!", event.getPlayer().name); event.getPlayer().savePlayerData(); } @@ -50,6 +54,12 @@ public void onPlayerChatInfo(PlayerChatEvent event) { LoggerFactory.getLogger("Room #" + event.getPlayer().getRoom().roomId).info("[{}] {}", event.getPlayer().name, event.getMessage()); } + @EventHandler + public void onPlayerReconnected(PlayerReconnectEvent event) { + event.getPlayer().getRoom().connectionManager.broadcastServerMessage(MessageFormat.format(LangUtil.getString("rukkit.playerReconnect"), event.getPlayer().name)); + LoggerFactory.getLogger("Room #" + event.getPlayer().getRoom().roomId).info("Player {} reconnected!", event.getPlayer().name); + } + @Override public void onLoad() { getLogger().info("BasePlugin::Load"); diff --git a/src/main/java/cn/rukkit/plugin/internal/CommandPlugin.java b/src/main/java/cn/rukkit/plugin/internal/CommandPlugin.java index f6bb197..281ac90 100644 --- a/src/main/java/cn/rukkit/plugin/internal/CommandPlugin.java +++ b/src/main/java/cn/rukkit/plugin/internal/CommandPlugin.java @@ -42,12 +42,13 @@ public class CommandPlugin extends InternalRukkitPlugin implements ChatCommandListener { - //int info = 0; + int totalInfo = 0; Logger log = LoggerFactory.getLogger(CommandPlugin.class); public class CommandEventListener implements EventListener { @EventHandler public void playerChat(PlayerChatEvent e) { + log.debug("admin = {}, voteId = {}", e.getPlayer().isAdmin, e.getPlayer().getRoom().vote.voteId); if (e.getPlayer().isAdmin && e.getPlayer().getRoom().vote.voteId.equals("afk")) { e.getPlayer().getRoom().connectionManager.broadcastServerMessage("Countdown stopped!"); e.getPlayer().getRoom().vote.stopVote(); @@ -110,14 +111,8 @@ public static class TeamChatCallback implements ChatCommandListener { @Override public boolean onSend(RoomConnection con, String[] args) { // TODO: Implement this method - for (RoomConnection conn : con.currectRoom.connectionManager.getConnections()) { - if (args.length < 1) return false; - if (conn.player.team == con.player.team && conn != null) { - conn.sendMessage(con.player.name, - LangUtil.getString("chat.teamMsg") + args[0], - con.player.playerIndex); - } - } + if (args.length < 1) return false; + con.player.sendTeamMessage(args[0]); return false; } } @@ -274,7 +269,7 @@ public boolean onSend(RoomConnection con, String[] cmd) { } else { try { if (cmd.length == 2) { - int team = Integer.parseInt(cmd[2]); + int team = Integer.parseInt(cmd[1]); if (team == -1 || team == -2) { if ((Integer.parseInt(cmd[0]) - 1) % 2 == 1) { @@ -292,7 +287,7 @@ public boolean onSend(RoomConnection con, String[] cmd) { con.sendServerMessage(LangUtil.getString("chat.playerExist")); } } catch (Exception e) { - e.printStackTrace(); + log.error("Error:", e); } } } @@ -383,7 +378,13 @@ public boolean onSend(RoomConnection con, String[] args) { class InfoCallback implements ChatCommandListener { @Override public boolean onSend(RoomConnection con, String[] args) { + totalInfo++; log.warn("{} send a info: {}", con.player.name, args[0]); + if (totalInfo >= 3) { + con.currectRoom.connectionManager.broadcastServerMessage("Desync founded!Server is resyncing..."); + con.currectRoom.syncGame(); + totalInfo = 0; + } return false; } } @@ -512,8 +513,8 @@ public boolean onSend(RoomConnection con, String[] args) { if (con.currectRoom.isGaming() || !con.player.isAdmin || args.length < 1) { // Do nothing. } else { - Rukkit.getRoundConfig().income = Integer.parseInt(args[0]); - if (Rukkit.getRoundConfig().income > 100 && Rukkit.getRoundConfig().income < 0) { + Rukkit.getRoundConfig().income = Float.parseFloat(args[0]); + if (Rukkit.getRoundConfig().income > 100 || Rukkit.getRoundConfig().income < 0) { Rukkit.getRoundConfig().income = 1; } try { @@ -691,7 +692,7 @@ public void run() { forePlayer.updateServerInfo(); currPlayer.updateServerInfo(); } - }, "afk", "Afk", 30); + }, "afk", LangUtil.getFormatString("chat.vote.afk", con.player.name), 30); return false; } } diff --git a/src/main/java/cn/rukkit/plugin/internal/ServerCommandPlugin.java b/src/main/java/cn/rukkit/plugin/internal/ServerCommandPlugin.java index eae0c32..637b2e8 100644 --- a/src/main/java/cn/rukkit/plugin/internal/ServerCommandPlugin.java +++ b/src/main/java/cn/rukkit/plugin/internal/ServerCommandPlugin.java @@ -19,6 +19,7 @@ import cn.rukkit.game.map.OfficialMap; import cn.rukkit.network.NetworkRoom; import cn.rukkit.network.RoomConnection; +import cn.rukkit.network.RoomManager; import cn.rukkit.network.packet.Packet; import cn.rukkit.plugin.PluginConfig; import cn.rukkit.util.LangUtil; @@ -26,6 +27,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -77,8 +79,11 @@ class PlayerListCallback implements ServerCommandListener { @Override public void onSend(String[] args) { StringBuffer buffer = new StringBuffer("- Players -\n"); - for (RoomConnection conn: Rukkit.getGlobalConnectionManager().getConnections()) { - buffer.append(String.format("%s (Team %d) (%d ms)\n",conn.player.name, conn.player.team, (System.currentTimeMillis() - conn.pingTime))); + for (NetworkRoom networkRoom: Rukkit.getRoomManager().roomList) { + buffer.append(MessageFormat.format("- Room #{0} (gaming={1})(step={2}) -\n", networkRoom.roomId, networkRoom.isGaming(), networkRoom.getCurrentStep())); + for (RoomConnection connection: networkRoom.connectionManager.getConnections()) { + buffer.append(MessageFormat.format("[{0}] {1} ping={2}\n", connection.player.playerIndex, connection.player.name, connection.player.ping)); + } } System.out.println(buffer); } diff --git a/src/main/java/cn/rukkit/plugin/internal/TestPlugin.java b/src/main/java/cn/rukkit/plugin/internal/TestPlugin.java index 5ff044d..b914d2c 100644 --- a/src/main/java/cn/rukkit/plugin/internal/TestPlugin.java +++ b/src/main/java/cn/rukkit/plugin/internal/TestPlugin.java @@ -64,7 +64,7 @@ public void onPing(PingEvent event) { try { player.getRoom().broadcast(Packet.gameSummon(player.getRoom(), unit, event.getTargetX(), event.getTargetY(), player.playerIndex)); } catch (IOException ignored) {} - player.putExtraData("isSpawnTriggered", false); + player.putTempData("isSpawnTriggered", false); } } diff --git a/src/main/java/cn/rukkit/util/LangUtil.java b/src/main/java/cn/rukkit/util/LangUtil.java index 1a066b4..a057a92 100644 --- a/src/main/java/cn/rukkit/util/LangUtil.java +++ b/src/main/java/cn/rukkit/util/LangUtil.java @@ -1,5 +1,6 @@ package cn.rukkit.util; import java.nio.charset.StandardCharsets; +import java.text.MessageFormat; import java.util.Locale; import java.util.ResourceBundle; @@ -18,4 +19,8 @@ public static String getString(String text) { } return new String(bundle.getString(text).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); } + + public static String getFormatString(String text, Object ... format) { + return MessageFormat.format(getString(text), format); + } } diff --git a/src/main/java/cn/rukkit/util/Vote.java b/src/main/java/cn/rukkit/util/Vote.java index 8c9f809..c4c380a 100644 --- a/src/main/java/cn/rukkit/util/Vote.java +++ b/src/main/java/cn/rukkit/util/Vote.java @@ -40,6 +40,7 @@ public boolean submitVoting(final Runnable runnable, String id, String reason, i RoomConnectionManager con = room.connectionManager; con.broadcastServerMessage(reason); timeRemain = timeRem; + voteId = id; voteDesc = reason; voteFuture = Rukkit.getThreadManager().schedule( new Runnable() { @@ -98,7 +99,6 @@ public void stopVote() { agree = disagree = 0; disabledVote = false; Arrays.fill(voteState, false); - if (voteFuture != null) - Rukkit.getThreadManager().shutdownTask(voteFuture); + if (voteFuture != null) Rukkit.getThreadManager().shutdownTask(voteFuture); } } \ No newline at end of file diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index 84d7f9c..f9bc9cb 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -44,6 +44,8 @@ chat.minStartPlayer=至少要 {0} 人才能开始游戏! chat.invalidCommand=指令不存在。输入 ".help" 查看指令帮助。 chat.privDenied=权限不足,无法使用! chat.afk=对挂机管理进行夺权。 +chat.vote.afk=玩家 {0} 发起对房主的 afk 请求! + # No stop plugin nostop.y=同意当前投票. nostop.n=反对当前投票. @@ -74,7 +76,10 @@ rukkit.playerLeft=玩家 {0} 离开了服务器! rukkit.gameFull=服务器已满! rukkit.playerGotAdmin=你现在是服务器内的管理员! rukkit.gameStarted=游戏已开始! -rukkit.playerReady=玩家 {0} 已准备. +rukkit.playerReady=玩家 {0} 已准备! +rukkit.playerReconnect=玩家 {0} 已重新连接! +rukkit.playerSharingControlDueDisconnected=断开连接时,自动分享控制. +rukkit.room=您现在在 {0} 号房间! # Plugin Load rukkit.plugin.invalid=Jar文件 {0}.jar 不是有效的 Rukkit 插件!请检查 plugin.yml! \ No newline at end of file diff --git a/src/main/resources/i18n/messages_en_US.properties b/src/main/resources/i18n/messages_en_US.properties index a01850a..7bc677a 100644 --- a/src/main/resources/i18n/messages_en_US.properties +++ b/src/main/resources/i18n/messages_en_US.properties @@ -59,6 +59,7 @@ nostop.vote.sync=Player {0} wants to resync.Send(-y/-n) to argee/disargee! nostop.vote.income=Player {0} wants to change income rate to {1}x.Send(-y/-n) to argee/disargee! nostop.vote.nukes=Player {0} wants to change nukes to {1}.Send(-y/-n) to argee/disargee! nostop.move=Player {0} moved his position from {1} to {2}! +chat.vote.afk=Player {0} requested to afk the admin! # Server command. server.kickAll=Kick current players in server. @@ -67,9 +68,12 @@ server.say=Say a message from server. # Rukkit base rukkit.playerRegister=You are logging to Rukkit. +rukkit.room=You are in the Room #{0}! rukkit.playerJoin=Player {0} joined the server! rukkit.playerLeft=Player {0} left the server! rukkit.gameFull=Game is full! rukkit.playerGotAdmin=You are the ADMIN of this server! rukkit.gameStarted=Game is started! -rukkit.playerReady=Player {0} is ready. \ No newline at end of file +rukkit.playerReady=Player {0} is ready. +rukkit.playerReconnect=Player {0} reconnected! +rukkit.playerSharingControlDueDisconnected=Sharing control due to disconnected. \ No newline at end of file diff --git a/src/main/resources/i18n/messages_zh_CN.properties b/src/main/resources/i18n/messages_zh_CN.properties index 87a2cb1..e5eb428 100644 --- a/src/main/resources/i18n/messages_zh_CN.properties +++ b/src/main/resources/i18n/messages_zh_CN.properties @@ -44,6 +44,8 @@ chat.minStartPlayer=至少要 {0} 人才能开始游戏! chat.invalidCommand=指令不存在。输入 ".help" 查看指令帮助。 chat.privDenied=权限不足,无法使用! chat.afk=对挂机管理进行夺权。 +chat.vote.afk=玩家 {0} 发起对房主的 afk 请求! + # No stop plugin nostop.y=同意当前投票. nostop.n=反对当前投票. @@ -54,7 +56,7 @@ nostop.vote.success={0} 人同意, {1} 人拒绝.投票成功! nostop.vote.failure={0} 人同意, {1} 人拒绝.投票失败! nostop.vote.timeRemain=时间剩余 {0} 秒! nostop.vote.voteExist=已经有一个投票在进行了! -nostop.vote.joinMessage={0} +nostop.vote.joinMessage={0} 加入了游戏! nostop.vote.map=玩家 {0} 投票更换地图到 {1}.发送(-y或-n) 来 同意/反对该投票! nostop.vote.cmap=玩家 {0} 投票更换自定义地图到 {1}.发送(-y或-n) 来 同意/反对该投票! nostop.vote.sync=玩家 {0} 投票进行游戏同步.发送(-y或-n) 来 同意/反对该投票! @@ -74,7 +76,10 @@ rukkit.playerLeft=玩家 {0} 离开了服务器! rukkit.gameFull=服务器已满! rukkit.playerGotAdmin=你现在是服务器内的管理员! rukkit.gameStarted=游戏已开始! -rukkit.playerReady=玩家 {0} 已准备. +rukkit.playerReady=玩家 {0} 已准备! +rukkit.playerReconnect=玩家 {0} 已重新连接! +rukkit.playerSharingControlDueDisconnected=断开连接时,自动分享控制. +rukkit.room=您现在在 {0} 号房间! # Plugin Load rukkit.plugin.invalid=Jar文件 {0}.jar 不是有效的 Rukkit 插件!请检查 plugin.yml! \ No newline at end of file