├── .classpath ├── .gitignore ├── .project ├── GetStarted.md ├── LICENSE ├── Plugin.md ├── README.md ├── README_zh.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── rukkit.png ├── settings.gradle ├── src └── main │ ├── java │ └── cn │ │ └── rukkit │ │ ├── Launsjsnsnsn.java │ │ ├── Rukkit.java │ │ ├── RukkitLauncher.java │ │ ├── RukkitSaveReader.java │ │ ├── command │ │ ├── ChatCommand.java │ │ ├── ChatCommandListener.java │ │ ├── Command.java │ │ ├── CommandHandler.java │ │ ├── CommandManager.java │ │ ├── ServerCommand.java │ │ ├── ServerCommandCompleter.java │ │ ├── ServerCommandListener.java │ │ └── completer │ │ │ └── PlayerCompleter.java │ │ ├── config │ │ ├── BaseConfig.java │ │ ├── RoundConfig.java │ │ └── RukkitConfig.java │ │ ├── event │ │ ├── Cancellable.java │ │ ├── Event.java │ │ ├── EventHandler.java │ │ ├── EventListener.java │ │ ├── EventListenerContainer.java │ │ ├── ListenerList.java │ │ ├── action │ │ │ ├── ActionEvent.java │ │ │ ├── BuildEvent.java │ │ │ ├── MoveEvent.java │ │ │ ├── PingEvent.java │ │ │ ├── RallyEvent.java │ │ │ └── TaskEvent.java │ │ ├── player │ │ │ ├── OnPlayerPreRegisterEvent.java │ │ │ ├── PlayerChatEvent.java │ │ │ ├── PlayerEvent.java │ │ │ ├── PlayerJoinEvent.java │ │ │ ├── PlayerLeftEvent.java │ │ │ └── PlayerReconnectEvent.java │ │ ├── room │ │ │ ├── RoomStartGameEvent.java │ │ │ └── RoomStopGameEvent.java │ │ └── server │ │ │ ├── ServerEvent.java │ │ │ └── ServerQuestionRespondEvent.java │ │ ├── game │ │ ├── CheckSumList.java │ │ ├── GameActions.java │ │ ├── GlobalPlayerManager.java │ │ ├── NetworkPlayer.java │ │ ├── NetworkPlayerData.java │ │ ├── PingType.java │ │ ├── PlayerManager.java │ │ ├── SaveData.java │ │ ├── SaveManager.java │ │ ├── UnitType.java │ │ ├── map │ │ │ ├── CustomMapLoader.java │ │ │ └── OfficialMap.java │ │ ├── mod │ │ │ ├── Mod.java │ │ │ ├── ModLoader.java │ │ │ └── ModManager.java │ │ └── unit │ │ │ └── InternalUnit.java │ │ ├── network │ │ ├── Connection.java.bak │ │ ├── ConnectionHandler.java │ │ ├── GameInputStream.java │ │ ├── GameOutputStream.java │ │ ├── GameServer.java.bak │ │ ├── GlobalConnectionManager.java │ │ ├── GzipDecoder.java │ │ ├── GzipEncoder.java │ │ ├── NetworkRoom.java │ │ ├── RoomConnection.java │ │ ├── RoomConnectionManager.java │ │ ├── RoomGameServer.java │ │ ├── RoomManager.java │ │ ├── command │ │ │ └── GameCommand.java │ │ └── packet │ │ │ ├── Packet.java │ │ │ ├── PacketDecoder.java │ │ │ └── PacketEncoder.java │ │ ├── plugin │ │ ├── Plugin.java │ │ ├── PluginConfig.java │ │ ├── PluginManager.java │ │ ├── RukkitPlugin.java │ │ └── internal │ │ │ ├── BasePlugin.java │ │ │ ├── CommandPlugin.java │ │ │ ├── InternalRukkitPlugin.java │ │ │ ├── NoStopCommandPlugin.java │ │ │ ├── ScriptPlugin.java │ │ │ ├── ServerCommandPlugin.java │ │ │ ├── TestPlugin.java │ │ │ └── TestPluginConfig.java │ │ ├── service │ │ ├── Service.java │ │ ├── ServiceManager.java │ │ ├── TerminalService.java │ │ └── ThreadManager.java │ │ └── util │ │ ├── GameUtils.java │ │ ├── LangUtil.java │ │ ├── MathUtil.java │ │ ├── VerifyUtil.java │ │ └── Vote.java │ └── resources │ ├── defaultSave │ ├── i18n │ ├── messages.properties │ ├── messages_en_US.properties │ ├── messages_ru.properties │ └── messages_zh_CN.properties │ ├── logback.xml │ ├── mod_default.1.14.json │ └── mod_default.json ├── start.bat └── start.sh /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | #VsCode file 28 | .vscode/ 29 | 30 | # Proguard folder generated by Eclipse 31 | proguard/ 32 | 33 | # Log Files 34 | *.log 35 | 36 | # Android Studio Navigation editor temp files 37 | .navigation/ 38 | 39 | # Android Studio captures folder 40 | captures/ 41 | 42 | # IntelliJ 43 | *.iml 44 | .idea/workspace.xml 45 | .idea/tasks.xml 46 | .idea/gradle.xml 47 | .idea/assetWizardSettings.xml 48 | .idea/dictionaries 49 | .idea/libraries 50 | # Android Studio 3 in .gitignore file. 51 | .idea/caches 52 | .idea/modules.xml 53 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 54 | .idea/navEditor.xml 55 | 56 | # Keystore files 57 | # Uncomment the following lines if you do not want to check your keystore files in. 58 | #*.jks 59 | #*.keystore 60 | 61 | # External native build folder generated in Android Studio 2.2 and later 62 | .externalNativeBuild 63 | .cxx/ 64 | 65 | # Google Services (e.g. APIs or Firebase) 66 | # google-services.json 67 | 68 | # Freeline 69 | freeline.py 70 | freeline/ 71 | freeline_project_description.json 72 | 73 | # fastlane 74 | fastlane/report.xml 75 | fastlane/Preview.html 76 | fastlane/screenshots 77 | fastlane/test_output 78 | fastlane/readme.md 79 | 80 | # Version control 81 | vcs.xml 82 | 83 | # lint 84 | lint/intermediates/ 85 | lint/generated/ 86 | lint/outputs/ 87 | lint/tmp/ 88 | # lint/reports/ 89 | 90 | # Rukkit generated dir 91 | maps/ 92 | mods/ 93 | plugins/ 94 | 95 | rukkit.yml 96 | round.yml 97 | server.properties 98 | .idea -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Rukkit 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /GetStarted.md: -------------------------------------------------------------------------------- 1 | ## How to compile rukkit? 2 | Rukkit now support gradle.Just using gradle to compile this project. 3 | 4 | For example: 5 | 1. clone this project. 6 | ```shell 7 | git clone https://github.com/RukkitDev/Rukkit 8 | ``` 9 | 2. using gradle to run a Rukkit server: 10 | ```shell 11 | gradle run 12 | ``` 13 | 3. or compile the project. 14 | ```shell 15 | gradle buildRukkit 16 | ``` 17 | 4. check the dir build/outputs and run start.sh/start.bat,and enjoy your server! -------------------------------------------------------------------------------- /Plugin.md: -------------------------------------------------------------------------------- 1 | # Plugin indroduction 2 | ## Getting started 3 | to start a plugin project, you need to import the whole dependences in libs,including current rukkit release. 4 | ## First Plugin 5 | to start with this framework: 6 | 7 | - src 8 | - MyPlugin.java 9 | - plugin.yml 10 | 11 | ### plugin.yml 12 | ```yaml 13 | author: author-name 14 | version: 1.0.0 15 | name: my-plugin 16 | #Plugin API version to support. 17 | apiVersion: 0.5.x 18 | #Main Plugin Class to load. 19 | pluginClass: MyPlugin 20 | ``` 21 | 22 | ### MyPlugin.java 23 | ```java 24 | public class MyPlugin extends RukkitPlugin { 25 | //Executes when PluginManager init 26 | @Override 27 | public void onStart() { 28 | //Do something... 29 | } 30 | //Executes when Server Started. 31 | @Override 32 | public void onDone() { 33 | //Do something... 34 | } 35 | //Executes when Server stopped. 36 | @Override 37 | public void onStop() { 38 | //Do something... 39 | } 40 | } 41 | ``` 42 | 43 | Packed them to jar, drop jar into server/plugins folder.You might see this: 44 | ```txt 45 | PluginManager::Loading my-plugin(v1.0.0)... 46 | ``` 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [中文](README_zh.md) 2 | 3 | # Rukkit Project 4 | ![RukkitLogo](rukkit.png) 5 | [![](https://img.shields.io/badge/QQ群-751977820-red.svg)]({linkUrl}) 6 | [![](https://img.shields.io/badge/Discord-link-purple.svg)](https://discord.gg/JJJ6GST) 7 | ## What is Rukkit? 8 | Rukkit is a Rustedwarfare Server,you can use it to run a private server on your vps or other devices. 9 | It's more like Dedicated server but more features like custom maps or mods, extra plugins. 10 | This project based on netty framework so it as stable as Dedicated Servers. 11 | 12 | ## Progress 13 | - [x] Basic Game Play 14 | - [x] Custom maps 15 | - [x] Game sync & rejoin (support offical maps and custom too) 16 | - [x] Basic Plugin System 17 | - [x] Mod server by mod's metadata (need a exportTool) 18 | - [x] 10p+ Multiplayer supported (only 1.14+) 19 | - [ ] No-stop game future. 20 | - [ ] Game hook(Events) supported some event not all. 21 | - [ ] Anti-Cheat sync (need a game Simulation layer) 22 | - [ ] Advanced gameCommand & save modification. (it's hard to make changes to them,the most result is crash the game.) 23 | - [ ] Relay mode (maybe in future version) 24 | 25 | ## About 26 | Some plugin system design referenced [Nukkit](https://github.com/Nukkit/Nukkit). 27 | 28 | ## Unstable warning 29 | this is still a unstable build.If you find bugs,please commit issues. 30 | if you fixed some bugs, you can have a PR. 31 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | # Rukkit 项目 2 | ![RukkitLogo](rukkit.png) 3 | [![](https://img.shields.io/badge/QQ群-751977820-red.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ekpIy0vjVhGpCZ5cpszxP6vaR9nRIaFc&authKey=wtgSzxj7uZ7zk%2F4GO20B%2FWVXP9WcZMC7c2FMynjZkx8B%2BkntiSeybBZZ6O3g7p90&noverify=0&group_code=751977820) 4 | [![](https://img.shields.io/badge/Discord-link-purple.svg)](https://discord.gg/JJJ6GST) 5 | ## 什么是 Rukkit? 6 | Rukkit是一个第三方铁锈战争服务器,你可以使用它来构建铁锈托管服务器,拥有类官服体验,性能更好,功能更强,支持自定义mod/地图和服务器插件,拥有游戏监听机制,允许你在游戏时拓展你的游戏体验,或是在游戏中创造新的玩法。Rukkit基于netty高性能框架,理论性能比官房/客户端更强。 7 | 8 | ## 目前进度 9 | - [x] 基础游戏(能玩) 10 | - [x] 自定义地图 11 | - [x] 游戏同步/玩家重进(只支持官方地图) 12 | - [x] 服务端插件系统 13 | - [x] 基于元信息的mod系统(需要拿工具转换rwmod) 14 | - [x] 10人以上玩家支持 (1.14+) 15 | - [ ] 不停止模式(支持随进随出,投票换图) 16 | - [ ] 游戏事件机制(支持一些) 17 | - [ ] 反作弊检查(需要游戏模拟层,做不出) 18 | - [ ] 游戏指令重构建. (比较困难,而且容易炸游戏.) 19 | - [ ] 中继模式 (咕咕咕) 20 | 21 | ## 关于 22 | 插件系统设计借鉴[Nukkit](https://github.com/Nukkit/Nukkit) 23 | 24 | ## 不稳定警告 25 | 这个版本仍然不稳定。如果你发现的bug 请提出issue,或者PR,感谢你的支持! 26 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This build file was generated by the Gradle 'init' task. 3 | * 4 | * This generated file contains a commented-out sample Java project to get you started. 5 | * For more details take a look at the Java Quickstart chapter in the Gradle 6 | * user guide available at https://docs.gradle.org/4.4.1/userguide/tutorial_java_projects.html 7 | */ 8 | 9 | // Apply the java plugin to add support for Java 10 | plugins { 11 | id 'java' 12 | id 'application' 13 | id 'com.github.johnrengelman.shadow' version '7.0.0' 14 | } 15 | 16 | [compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF8' 17 | final def RUKKIT_VERSION = "0.9.4-dev" 18 | mainClassName = 'cn.rukkit.RukkitLauncher' 19 | 20 | // In this section you declare where to find the dependencies of your project 21 | repositories { 22 | // Use 'jcenter' for resolving your dependencies. 23 | // You can declare any Maven/Ivy/file repository here. 24 | mavenCentral() 25 | } 26 | 27 | // In this section you declare the dependencies for your production and test code 28 | dependencies { 29 | // The production code uses the SLF4J logging API at compile time 30 | // compile 'org.slf4j:slf4j-api:1.7.25' 31 | implementation 'com.alibaba.fastjson2:fastjson2:2.0.41' 32 | implementation 'org.jline:jline-terminal:3.25.0' 33 | implementation 'org.jline:jline-console:3.25.0' 34 | implementation 'org.jline:jline:3.25.0' 35 | implementation 'org.jline:jline-reader:3.25.0' 36 | implementation 'org.jline:jline-terminal-jna:3.25.0' 37 | // https://mvnrepository.com/artifact/io.netty/netty-all 38 | implementation 'io.netty:netty-all:4.1.100.Final' 39 | implementation 'ch.qos.logback:logback-core:1.4.14' 40 | implementation 'ch.qos.logback:logback-classic:1.4.12' 41 | implementation 'org.slf4j:slf4j-api:2.0.7' 42 | implementation 'org.yaml:snakeyaml:2.0' 43 | 44 | 45 | //compile 'netty' 46 | // Declare the dependency for your favourite test framework you want to use in your tests. 47 | // TestNG is also supported by the Gradle Test task. Just change the 48 | // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add 49 | // 'test.useTestNG()' to your build script. 50 | //testCompile 'junit:junit:4.12' 51 | } 52 | 53 | tasks.withType(Javadoc).configureEach { 54 | options.encoding = 'UTF-8' 55 | } 56 | 57 | tasks.register('buildRukkit') { 58 | dependsOn shadowJar 59 | doLast { 60 | println("Okay.Doing last step...") 61 | mkdir("./build/outputs") 62 | /*copy() { 63 | CopySpec copySpec -> 64 | from file("${rootDir}/libs") 65 | into "${rootDir}/build/outputs/libs" 66 | }*/ 67 | copy() { 68 | CopySpec copySpec -> 69 | from file("${rootDir}/build/libs/Rukkit-all.jar") 70 | into "${rootDir}/build/outputs/" 71 | rename('Rukkit-all.jar', "Rukkit-${RUKKIT_VERSION}.jar") 72 | } 73 | copy() { 74 | CopySpec copySpec -> 75 | from file("${rootDir}/start.sh") 76 | into "${rootDir}/build/outputs/" 77 | } 78 | copy() { 79 | CopySpec copySpec -> 80 | from file("${rootDir}/start.bat") 81 | into "${rootDir}/build/outputs/" 82 | } 83 | replaceFileText(new File("${rootDir}/build/outputs/start.sh"), "\\{version\\}", RUKKIT_VERSION) 84 | replaceFileText(new File("${rootDir}/build/outputs/start.bat"), "\\{version\\}", RUKKIT_VERSION) 85 | println(""" 86 | -- Well done! -- 87 | targetRukkitVersion: ${RUKKIT_VERSION} 88 | Check the build/outputs to get the result. 89 | """) 90 | } 91 | } 92 | 93 | static def replaceFileText(file, oldText, newText) { 94 | String text = file.text.replaceAll(oldText, newText) 95 | file.withPrintWriter { printWriter -> 96 | printWriter.print(text) 97 | } 98 | } 99 | 100 | 101 | jar { 102 | manifest { 103 | attributes 'Main-Class': 'cn.rukkit.RukkitLauncher' 104 | } 105 | } 106 | 107 | shadowJar { 108 | 109 | } 110 | 111 | run {} 112 | 113 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RukkitDev/Rukkit/4764085cda35428fe920ecbd0fbc2fd70c6f72b2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020-2022 RukkitDev Team and contributors. 3 | # 4 | # This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | # 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | # 7 | # https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | # 9 | 10 | # 11 | # Copyright 2020-2022 RukkitDev Team and contributors. 12 | # 13 | 14 | distributionBase=GRADLE_USER_HOME 15 | distributionPath=wrapper/dists 16 | zipStoreBase=GRADLE_USER_HOME 17 | zipStorePath=wrapper/dists 18 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 19 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2020-2022 RukkitDev Team and contributors. 5 | # 6 | # This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 7 | # 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 8 | # 9 | # https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 10 | # 11 | 12 | # 13 | # Copyright 2020-2022 RukkitDev Team and contributors. 14 | # 15 | 16 | ############################################################################## 17 | ## 18 | ## Gradle start up script for UN*X 19 | ## 20 | ############################################################################## 21 | 22 | # Attempt to set APP_HOME 23 | # Resolve links: $0 may be a link 24 | PRG="$0" 25 | # Need this for relative symlinks. 26 | while [ -h "$PRG" ] ; do 27 | ls=`ls -ld "$PRG"` 28 | link=`expr "$ls" : '.*-> \(.*\)$'` 29 | if expr "$link" : '/.*' > /dev/null; then 30 | PRG="$link" 31 | else 32 | PRG=`dirname "$PRG"`"/$link" 33 | fi 34 | done 35 | SAVED="`pwd`" 36 | cd "`dirname \"$PRG\"`/" >/dev/null 37 | APP_HOME="`pwd -P`" 38 | cd "$SAVED" >/dev/null 39 | 40 | APP_NAME="Gradle" 41 | APP_BASE_NAME=`basename "$0"` 42 | 43 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 44 | DEFAULT_JVM_OPTS="" 45 | 46 | # Use the maximum available, or set MAX_FD != -1 to use that value. 47 | MAX_FD="maximum" 48 | 49 | warn () { 50 | echo "$*" 51 | } 52 | 53 | die () { 54 | echo 55 | echo "$*" 56 | echo 57 | exit 1 58 | } 59 | 60 | # OS specific support (must be 'true' or 'false'). 61 | cygwin=false 62 | msys=false 63 | darwin=false 64 | nonstop=false 65 | case "`uname`" in 66 | CYGWIN* ) 67 | cygwin=true 68 | ;; 69 | Darwin* ) 70 | darwin=true 71 | ;; 72 | MINGW* ) 73 | msys=true 74 | ;; 75 | NONSTOP* ) 76 | nonstop=true 77 | ;; 78 | esac 79 | 80 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 81 | 82 | # Determine the Java command to use to start the JVM. 83 | if [ -n "$JAVA_HOME" ] ; then 84 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 85 | # IBM's JDK on AIX uses strange locations for the executables 86 | JAVACMD="$JAVA_HOME/jre/sh/java" 87 | else 88 | JAVACMD="$JAVA_HOME/bin/java" 89 | fi 90 | if [ ! -x "$JAVACMD" ] ; then 91 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 92 | 93 | Please set the JAVA_HOME variable in your environment to match the 94 | location of your Java installation." 95 | fi 96 | else 97 | JAVACMD="java" 98 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 99 | 100 | Please set the JAVA_HOME variable in your environment to match the 101 | location of your Java installation." 102 | fi 103 | 104 | # Increase the maximum file descriptors if we can. 105 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 106 | MAX_FD_LIMIT=`ulimit -H -n` 107 | if [ $? -eq 0 ] ; then 108 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 109 | MAX_FD="$MAX_FD_LIMIT" 110 | fi 111 | ulimit -n $MAX_FD 112 | if [ $? -ne 0 ] ; then 113 | warn "Could not set maximum file descriptor limit: $MAX_FD" 114 | fi 115 | else 116 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 117 | fi 118 | fi 119 | 120 | # For Darwin, add options to specify how the application appears in the dock 121 | if $darwin; then 122 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 123 | fi 124 | 125 | # For Cygwin, switch paths to Windows format before running java 126 | if $cygwin ; then 127 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 128 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 129 | JAVACMD=`cygpath --unix "$JAVACMD"` 130 | 131 | # We build the pattern for arguments to be converted via cygpath 132 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 133 | SEP="" 134 | for dir in $ROOTDIRSRAW ; do 135 | ROOTDIRS="$ROOTDIRS$SEP$dir" 136 | SEP="|" 137 | done 138 | OURCYGPATTERN="(^($ROOTDIRS))" 139 | # Add a user-defined pattern to the cygpath arguments 140 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 141 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 142 | fi 143 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 144 | i=0 145 | for arg in "$@" ; do 146 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 147 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 148 | 149 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 150 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 151 | else 152 | eval `echo args$i`="\"$arg\"" 153 | fi 154 | i=$((i+1)) 155 | done 156 | case $i in 157 | (0) set -- ;; 158 | (1) set -- "$args0" ;; 159 | (2) set -- "$args0" "$args1" ;; 160 | (3) set -- "$args0" "$args1" "$args2" ;; 161 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 162 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 163 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 164 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 165 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 166 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 167 | esac 168 | fi 169 | 170 | # Escape application args 171 | save () { 172 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 173 | echo " " 174 | } 175 | APP_ARGS=$(save "$@") 176 | 177 | # Collect all arguments for the java command, following the shell quoting and substitution rules 178 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 179 | 180 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 181 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 182 | cd "$(dirname "$0")" 183 | fi 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /rukkit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RukkitDev/Rukkit/4764085cda35428fe920ecbd0fbc2fd70c6f72b2/rukkit.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This settings file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * In a single project build this file can be empty or even removed. 6 | * 7 | * Detailed information about configuring a multi-project build in Gradle can be found 8 | * in the user guide at https://docs.gradle.org/4.4.1/userguide/multi_project_builds.html 9 | */ 10 | 11 | /* 12 | // To declare projects as part of a multi-project build use the 'include' method 13 | include 'shared' 14 | include 'api' 15 | include 'services:webservice' 16 | */ 17 | 18 | rootProject.name = 'Rukkit' 19 | ext { 20 | rukkitVersion = '0.8.0' 21 | supportGameVersion = '151' 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/Launsjsnsnsn.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit; 11 | 12 | public class Launsjsnsnsn 13 | { 14 | public static void start(String args[]) { 15 | // fuck! 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/RukkitLauncher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit; 11 | 12 | import ch.qos.logback.classic.layout.TTLLLayout; 13 | import ch.qos.logback.classic.spi.ILoggingEvent; 14 | import ch.qos.logback.core.ConsoleAppender; 15 | import ch.qos.logback.core.Layout; 16 | import cn.rukkit.command.ServerCommandCompleter; 17 | import io.netty.util.internal.logging.InternalLoggerFactory; 18 | import io.netty.util.internal.logging.Slf4JLoggerFactory; 19 | import org.jline.reader.EndOfFileException; 20 | import org.jline.reader.LineReader; 21 | import org.jline.reader.LineReaderBuilder; 22 | import org.jline.reader.UserInterruptException; 23 | import org.jline.reader.impl.completer.ArgumentCompleter; 24 | import org.jline.reader.impl.completer.NullCompleter; 25 | import org.jline.terminal.Terminal; 26 | import org.jline.terminal.TerminalBuilder; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | import java.io.IOException; 31 | 32 | public class RukkitLauncher extends ConsoleAppender 33 | { 34 | static Terminal terminal; 35 | static LineReader lineReader; 36 | public static final String PATTERN = ">"; 37 | static Thread terminalThread; 38 | static boolean isTerminalRunning = true; 39 | 40 | public static ServerCommandCompleter serverCommandCompleter = new ServerCommandCompleter(); 41 | 42 | private static Logger log = LoggerFactory.getLogger("Launcher"); 43 | public static void main(String args[]){ 44 | InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory()); 45 | try { 46 | log.info("init::JLine Terminal..."); 47 | terminal = TerminalBuilder.builder().system(true).jna(true).build(); 48 | lineReader = LineReaderBuilder.builder().terminal(terminal).completer(new ArgumentCompleter( 49 | serverCommandCompleter, 50 | NullCompleter.INSTANCE 51 | )).build(); 52 | Rukkit.startServer(); 53 | while (isTerminalRunning) { 54 | try { 55 | Thread.sleep(1); // 不知道为什么反正要这个东西 56 | if (Rukkit.getCommandManager() == null) continue; 57 | if (Rukkit.isStarted()) { 58 | serverCommandCompleter.setCommandCompleteVars(Rukkit.getCommandManager().getLoadedServerCommandStringList()); 59 | } else { 60 | continue; 61 | } 62 | String str = lineReader.readLine(PATTERN); 63 | Rukkit.getCommandManager().executeServerCommand(str); 64 | } 65 | catch (UserInterruptException e) { 66 | log.info("Stopping server..."); 67 | Rukkit.shutdown("Server stopped by console"); 68 | } 69 | catch (EndOfFileException e) { 70 | log.info("Stopping server..."); 71 | Rukkit.shutdown("Server stopped by console"); 72 | break; 73 | } 74 | catch (Exception e) { 75 | System.out.println("Oops.A exception occurred."); 76 | e.printStackTrace(); 77 | } 78 | } 79 | } catch (IOException e) { 80 | //e.printStackTrace(); 81 | } catch (InterruptedException e) { 82 | //e.printStackTrace(); 83 | } 84 | } 85 | 86 | Layout layout = new TTLLLayout(); 87 | 88 | private static void nop() {} 89 | 90 | 91 | @Override 92 | public void start() { 93 | super.start(); 94 | layout.start(); 95 | } 96 | 97 | @Override 98 | public void stop() { 99 | layout.stop(); 100 | super.stop(); 101 | } 102 | 103 | @Override 104 | protected void subAppend(ILoggingEvent event) { 105 | lineReader.printAbove(new String(encoder.encode(event))); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/command/ChatCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.command; 11 | import cn.rukkit.plugin.*; 12 | 13 | public class ChatCommand 14 | { 15 | public String cmd; 16 | public String helpMessage; 17 | public int args = 1; 18 | public boolean adminRequired = false; 19 | private boolean isEnabled = false; 20 | private ChatCommandListener chatListener; 21 | private RukkitPlugin fromPlugin; 22 | 23 | 24 | public ChatCommand(String msg, String helpMessage,int args, ChatCommandListener chatListener, RukkitPlugin fromPlugin) { 25 | this.cmd = msg; 26 | this.args = args; 27 | this.helpMessage = helpMessage; 28 | this.chatListener = chatListener; 29 | this.fromPlugin = fromPlugin; 30 | } 31 | 32 | public ChatCommand(String msg, String helpMessage,int args, ChatCommandListener chatListener, RukkitPlugin fromPlugin, boolean adminRequired) { 33 | this.cmd = msg; 34 | this.args = args; 35 | this.helpMessage = helpMessage; 36 | this.chatListener = chatListener; 37 | this.fromPlugin = fromPlugin; 38 | this.adminRequired = adminRequired; 39 | } 40 | 41 | public RukkitPlugin getFromPlugin() { 42 | return fromPlugin; 43 | } 44 | 45 | public void setEnabled(boolean isEnabled) { 46 | this.isEnabled = isEnabled; 47 | } 48 | 49 | public boolean isEnabled() { 50 | return isEnabled; 51 | } 52 | 53 | public void setListener(ChatCommandListener listener) { 54 | this.chatListener = listener; 55 | } 56 | 57 | public ChatCommandListener getListener() { 58 | return chatListener; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/command/ChatCommandListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.command; 11 | import cn.rukkit.network.*; 12 | 13 | public interface ChatCommandListener 14 | { 15 | public boolean onSend(RoomConnection con, String args[]); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/command/Command.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.command; 11 | import cn.rukkit.plugin.*; 12 | 13 | public class Command 14 | { 15 | public enum CommandType { 16 | CHAT, SERVER, BOTH 17 | } 18 | public String cmd; 19 | public String helpMessage; 20 | public int args = 1; 21 | private boolean isEnabled = false; 22 | private ChatCommandListener chatListener; 23 | private RukkitPlugin fromPlugin; 24 | public CommandType type; 25 | 26 | public Command(String msg, String helpMessage,int args, ChatCommandListener chatListener, RukkitPlugin fromPlugin, CommandType type) { 27 | this.cmd = msg; 28 | this.args = args; 29 | this.helpMessage = helpMessage; 30 | this.chatListener = chatListener; 31 | this.fromPlugin = fromPlugin; 32 | } 33 | 34 | public RukkitPlugin getFromPlugin() { 35 | return fromPlugin; 36 | } 37 | 38 | public void setEnabled(boolean isEnabled) { 39 | this.isEnabled = isEnabled; 40 | } 41 | 42 | public boolean isEnabled() { 43 | return isEnabled; 44 | } 45 | 46 | public void setListener(ChatCommandListener listener) { 47 | this.chatListener = listener; 48 | } 49 | 50 | public ChatCommandListener getListener() { 51 | return chatListener; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/command/CommandHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.command; 11 | 12 | public class CommandHandler 13 | { 14 | } -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/command/CommandManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.command; 11 | 12 | import java.util.*; 13 | 14 | import cn.rukkit.util.LangUtil; 15 | import org.jline.reader.Candidate; 16 | import org.jline.reader.Completer; 17 | import org.jline.reader.LineReader; 18 | import org.jline.reader.ParsedLine; 19 | import org.jline.reader.impl.completer.StringsCompleter; 20 | import org.slf4j.*; 21 | import cn.rukkit.network.*; 22 | import cn.rukkit.*; 23 | import cn.rukkit.network.packet.*; 24 | import java.io.*; 25 | 26 | public class CommandManager 27 | { 28 | private Logger log = LoggerFactory.getLogger(CommandManager.class); 29 | private HashMap loadedCommand = new HashMap(); 30 | private HashMap loadedServerCommand = new HashMap(); 31 | 32 | private List serverCmdString = new ArrayList<>(); 33 | 34 | public void registerCommand(ChatCommand cmd) { 35 | log.debug(String.format("Registering Command '%s' from plugin '%s'...",cmd.cmd,cmd.getFromPlugin().config.name)); 36 | if (fetchCommand(cmd.cmd) != null) { 37 | log.warn(String.format("Command '%s' had already registered.",cmd.cmd)); 38 | } else { 39 | loadedCommand.put(cmd.cmd, cmd); 40 | } 41 | } 42 | 43 | public void registerServerCommand(ServerCommand cmd) { 44 | log.debug(String.format("Registering ServerCommand '%s' from plugin '%s'...",cmd.cmd,cmd.getFromPlugin().config.name)); 45 | if (fetchServerCommand(cmd.cmd) != null) { 46 | log.warn(String.format("ServerCommand '%s' had already registered.",cmd.cmd)); 47 | } else { 48 | loadedServerCommand.put(cmd.cmd, cmd); 49 | serverCmdString.add(cmd.cmd); 50 | } 51 | } 52 | 53 | public void executeChatCommand(RoomConnection connection, String cmd) { 54 | String[] cmds = cmd.split("\\s+", 2); 55 | ChatCommand cmdObj = fetchCommand(cmds[0]); 56 | if (cmdObj == null) { 57 | connection.sendServerMessage(LangUtil.getString("chat.invalidCommand")); 58 | return; 59 | } else if (cmdObj.adminRequired){ 60 | if (!connection.player.isAdmin) { 61 | connection.sendServerMessage(LangUtil.getString("chat.privDenied")); 62 | return; 63 | } 64 | } 65 | boolean result; 66 | log.trace("cmd is:" + cmds[0]); 67 | if (cmds.length > 1 && cmdObj.args > 0) { 68 | String[] args = cmds[1].split(" ", cmdObj.args); 69 | result = cmdObj.getListener().onSend(connection,args); 70 | } else { 71 | result = cmdObj.getListener().onSend(connection,new String[0]); 72 | } 73 | if (result == true) { 74 | try { 75 | connection.currectRoom.broadcast( 76 | Packet.chat(connection.player.name, 77 | "-" + cmd, 78 | connection.player.playerIndex)); 79 | } catch (IOException e) {} 80 | } 81 | } 82 | 83 | public void executeServerCommand(String cmd) { 84 | String[] cmds = cmd.split("\\s+", 2); 85 | ServerCommand cmdObj = fetchServerCommand(cmds[0]); 86 | if (cmdObj == null) { 87 | System.out.println("Command not exist.Try 'help' to list all commands."); 88 | return; 89 | } 90 | log.trace("cmd is:" + cmds[0]); 91 | if (cmds.length > 1 && cmdObj.args > 0) { 92 | String[] args = cmds[1].split(" ", cmdObj.args); 93 | cmdObj.getListener().onSend(args); 94 | } else { 95 | cmdObj.getListener().onSend(new String[0]); 96 | } 97 | } 98 | 99 | 100 | public ChatCommand fetchCommand(String cmd){ 101 | return loadedCommand.getOrDefault(cmd, null); 102 | } 103 | 104 | public ServerCommand fetchServerCommand(String cmd) { 105 | return loadedServerCommand.getOrDefault(cmd, null); 106 | } 107 | 108 | public HashMap getLoadedCommand() { 109 | return loadedCommand; 110 | } 111 | 112 | public HashMap getLoadedServerCommand() { 113 | return loadedServerCommand; 114 | } 115 | 116 | public List getLoadedServerCommandStringList() { 117 | return serverCmdString; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/command/ServerCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.command; 11 | 12 | import cn.rukkit.plugin.RukkitPlugin; 13 | 14 | public class ServerCommand { 15 | public String cmd; 16 | public String helpMessage; 17 | public int args = 1; 18 | private boolean isEnabled = false; 19 | private ServerCommandListener serverCommandListener; 20 | private RukkitPlugin fromPlugin; 21 | 22 | public ServerCommand(String msg, String helpMessage,int args, ServerCommandListener chatListener, RukkitPlugin fromPlugin) { 23 | this.cmd = msg; 24 | this.args = args; 25 | this.helpMessage = helpMessage; 26 | this.serverCommandListener = chatListener; 27 | this.fromPlugin = fromPlugin; 28 | } 29 | 30 | public RukkitPlugin getFromPlugin() { 31 | return fromPlugin; 32 | } 33 | 34 | public void setEnabled(boolean isEnabled) { 35 | this.isEnabled = isEnabled; 36 | } 37 | 38 | public boolean isEnabled() { 39 | return isEnabled; 40 | } 41 | 42 | public void setListener(ServerCommandListener listener) { 43 | this.serverCommandListener = listener; 44 | } 45 | 46 | public ServerCommandListener getListener() { 47 | return serverCommandListener; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/command/ServerCommandCompleter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.command; 11 | 12 | import org.jline.reader.Candidate; 13 | import org.jline.reader.Completer; 14 | import org.jline.reader.LineReader; 15 | import org.jline.reader.ParsedLine; 16 | import org.jline.reader.impl.completer.StringsCompleter; 17 | 18 | import java.util.List; 19 | 20 | public class ServerCommandCompleter implements Completer { 21 | 22 | Completer completer; 23 | 24 | public ServerCommandCompleter() { 25 | this.completer = new StringsCompleter(); 26 | } 27 | 28 | @Override 29 | public void complete(LineReader reader, ParsedLine line, List candidates) { 30 | completer.complete(reader, line, candidates); 31 | } 32 | 33 | public void setCommandCompleteVars(List fileVars) { 34 | this.completer = new StringsCompleter(fileVars); 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/command/ServerCommandListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.command; 11 | 12 | public interface ServerCommandListener { 13 | public void onSend(String args[]); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/command/completer/PlayerCompleter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.command.completer; 11 | 12 | import org.jline.reader.Candidate; 13 | import org.jline.reader.Completer; 14 | import org.jline.reader.LineReader; 15 | import org.jline.reader.ParsedLine; 16 | import org.jline.reader.impl.completer.StringsCompleter; 17 | 18 | import java.util.List; 19 | 20 | public class PlayerCompleter extends StringsCompleter { 21 | Completer completer; 22 | 23 | @Override 24 | public void complete(LineReader reader, ParsedLine commandLine, List candidates) { 25 | StringsCompleter stringsCompleter = new StringsCompleter(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/config/BaseConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.config; 11 | 12 | import cn.rukkit.*; 13 | import java.io.*; 14 | import org.yaml.snakeyaml.*; 15 | //import java.util.logging.*; 16 | import org.slf4j.*; 17 | import org.yaml.snakeyaml.nodes.Tag; 18 | 19 | public abstract class BaseConfig 20 | { 21 | Logger log = LoggerFactory.getLogger(this.getClass()); 22 | public String configName; 23 | //public abstract void ConfigFile(); 24 | public BaseConfig loadConfig() throws IllegalAccessException, InstantiationException, IOException { 25 | this.getClass().newInstance(); 26 | File confFile = new File(Rukkit.getEnvPath() + configName); 27 | if (confFile.exists() && confFile.isFile()) { 28 | log.debug("Found Config file.Reading..."); 29 | return new Yaml().loadAs(new FileReader(confFile), this.getClass()); 30 | } else { 31 | log.debug("Config file.not found.Creating..."); 32 | confFile.delete(); 33 | confFile.createNewFile(); 34 | BaseConfig cfg = this.getClass().newInstance(); 35 | FileWriter writer = new FileWriter(confFile); 36 | writer.write(new Yaml().dumpAs(cfg, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); 37 | writer.flush(); 38 | writer.close(); 39 | return cfg; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/config/RoundConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.config; 11 | 12 | public class RoundConfig extends BaseConfig 13 | { 14 | /*Dynamic Properties*/ 15 | public String mapName = "[z;p10]Crossing Large (10p)"; 16 | public int mapType = 0; 17 | public float income = 1.0f; 18 | public int credits = 4000; 19 | public boolean disableNuke = true; 20 | public boolean sharedControl = false; 21 | public int fogType = 2; 22 | public int startingUnits = 1; 23 | //public String configName = "round.yml"; 24 | 25 | public RoundConfig() { 26 | this.configName = "round.yml"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/config/RukkitConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.config; 11 | 12 | import java.util.Locale; 13 | 14 | public class RukkitConfig extends BaseConfig 15 | { 16 | public String serverUser = "RUKKIT"; 17 | public String welcomeMsg = "Welcome to Rukkit server, {playerName}!"; 18 | public String serverMotd = "My Rukkit server"; 19 | public int serverPort = 5123; 20 | public int maxPlayer = 10; 21 | public int maxRoom = 5; 22 | public int minStartPlayer = 4; 23 | public boolean syncEnabled = true; 24 | public boolean singlePlayerMode = false; 25 | public boolean isDebug = true; 26 | public boolean onlineMode = false; 27 | public String logPath = "/sdcard/rukkit-error.log"; 28 | public int maxPacketFrame = 8192; 29 | public String UUID = "00000000-0000-0000-0000-000000000000"; 30 | public String lang = Locale.getDefault().toString(); 31 | //max threads in manager.Default = 8; 32 | public int threadPoolCount = 8; 33 | // max unit in per player 单玩家最大单位 34 | public int maxUnitsPerPlayer = 250; 35 | // using question system to vote 投票系统使用提示框模式实现 36 | // public boolean usingPopupInVote = false; 37 | 38 | //Ping packet receive timeout.default = 8000 (ms) 39 | public int pingTimeout = 8000; 40 | 41 | //registerTimeout default = 5 (s) 42 | public int registerTimeout = 5; 43 | 44 | //Using commandQuere to manage game commands 45 | public boolean useCommandQuere = false; 46 | 47 | public boolean checksumSync = false; 48 | 49 | public RukkitConfig() { 50 | this.configName = "rukkit.yml"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/Cancellable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event; 11 | 12 | public interface Cancellable 13 | { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/Event.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event; 11 | 12 | public class Event 13 | { 14 | public boolean isCancelled = false; 15 | 16 | public void setCancel(boolean cancel) { 17 | if (this instanceof Cancellable) { 18 | this.isCancelled = cancel; 19 | } else { 20 | //throw new RuntimeException("Event not cancellable"); 21 | //Do nothing. 22 | } 23 | } 24 | 25 | public boolean isCancelled() { 26 | if (this instanceof Cancellable) { 27 | return isCancelled; 28 | } else { 29 | //throw new RuntimeException("Event not cancellable"); 30 | return false; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/EventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event; 11 | 12 | import java.lang.annotation.*; 13 | 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface EventHandler 16 | { 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/EventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event; 11 | 12 | public interface EventListener 13 | { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/EventListenerContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event; 11 | 12 | import cn.rukkit.plugin.*; 13 | import java.lang.reflect.*; 14 | import java.util.*; 15 | 16 | public class EventListenerContainer 17 | { 18 | public Method method; 19 | public RukkitPlugin plugin; 20 | public EventListener listener; 21 | public EventListenerContainer(RukkitPlugin plugin, Method method, EventListener listener){ 22 | this.method = method; 23 | this.listener = listener; 24 | this.plugin = plugin; 25 | } 26 | 27 | public Event callMethod(Event event) { 28 | method.setAccessible(true); 29 | try 30 | { 31 | method.invoke(listener, event); 32 | //listener.invoke(new PlayerJoinEvent(), new PlayerJoinEvent()); 33 | } 34 | catch (IllegalAccessException e) 35 | { 36 | e.printStackTrace(); 37 | } 38 | catch (IllegalArgumentException e) 39 | { 40 | e.printStackTrace(); 41 | } 42 | catch (InvocationTargetException e) 43 | { 44 | e.printStackTrace(); 45 | } 46 | return event; 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/ListenerList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event; 11 | 12 | import cn.rukkit.event.*; 13 | import java.util.*; 14 | import cn.rukkit.util.*; 15 | import org.slf4j.*; 16 | import cn.rukkit.plugin.RukkitPlugin; 17 | 18 | public class ListenerList 19 | { 20 | private Class eventClass; 21 | private static Logger log; 22 | private ArrayList listenerList = new ArrayList(); 23 | 24 | public ListenerList(Class clazz) { 25 | this.eventClass = clazz; 26 | this.log = LoggerFactory.getLogger("List" + eventClass.toString()); 27 | } 28 | 29 | public void registerListener(EventListenerContainer listener) { 30 | this.listenerList.add(listener); 31 | } 32 | 33 | public boolean callListeners(Event event) { 34 | for(EventListenerContainer listener : listenerList) { 35 | Event e = listener.callMethod(event); 36 | log.debug("isCanceled: " + e.isCancelled); 37 | if (e.isCancelled) { 38 | return false; 39 | } 40 | } 41 | return true; 42 | } 43 | 44 | public void removePluginListener(EventListener listener) { 45 | // 更安全的移除 46 | Iterator iterator = listenerList.iterator(); 47 | while (iterator.hasNext()) { 48 | EventListenerContainer container = iterator.next(); 49 | if (container.listener.getClass() == listener.getClass()) { 50 | iterator.remove(); 51 | } 52 | } 53 | /* 54 | for (EventListenerContainer c: listenerList) { 55 | if (c.listener.getClass() == listener.getClass()) { 56 | listenerList.remove(c); 57 | } 58 | }*/ 59 | } 60 | 61 | public void clear() { 62 | this.listenerList.clear(); 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/action/ActionEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.action; 11 | import cn.rukkit.event.*; 12 | 13 | public class ActionEvent extends Event 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/action/BuildEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.action; 11 | 12 | import cn.rukkit.event.*; 13 | import cn.rukkit.event.action.*; 14 | import cn.rukkit.game.*; 15 | 16 | public class BuildEvent extends ActionEvent implements Cancellable 17 | { 18 | private static ListenerList list = new ListenerList(BuildEvent.class); 19 | 20 | public static ListenerList getListenerList() { 21 | return list; 22 | } 23 | 24 | private float targetX; 25 | 26 | private float targetY; 27 | 28 | private String targetUnitName; 29 | 30 | private long fromUnitId; 31 | private NetworkPlayer player; 32 | 33 | public float getTargetX() 34 | { 35 | return targetX; 36 | } 37 | 38 | public float getTargetY() 39 | { 40 | return targetY; 41 | } 42 | 43 | public String getTargetUnitName() 44 | { 45 | return targetUnitName; 46 | } 47 | 48 | public long getFromUnitId() 49 | { 50 | return fromUnitId; 51 | } 52 | 53 | public NetworkPlayer getPlayer() { 54 | return this.player; 55 | } 56 | 57 | public BuildEvent (NetworkPlayer p, float targetX, float targetY, long fromUnitId, String targetUnitName) { 58 | this.player = p; 59 | this.targetX = targetX; 60 | this.targetY = targetY; 61 | this.fromUnitId = fromUnitId; 62 | this.targetUnitName = targetUnitName; 63 | } 64 | 65 | public BuildEvent (NetworkPlayer p, float targetX, float targetY, String targetUnitName) { 66 | this.player = p; 67 | this.targetX = targetX; 68 | this.targetY = targetY; 69 | this.fromUnitId = 0; 70 | this.targetUnitName = targetUnitName; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/action/MoveEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.action; 11 | 12 | import cn.rukkit.event.*; 13 | import cn.rukkit.event.action.*; 14 | import cn.rukkit.game.*; 15 | 16 | public class MoveEvent extends ActionEvent implements Cancellable 17 | { 18 | private static ListenerList list = new ListenerList(MoveEvent.class); 19 | 20 | public static ListenerList getListenerList() { 21 | return list; 22 | } 23 | 24 | private NetworkPlayer player; 25 | private float targetX; 26 | private float targetY; 27 | private long actionUnitId; 28 | 29 | public MoveEvent(NetworkPlayer p, float x, float y, long id){ 30 | this.player = p; 31 | this.targetX = x; 32 | this.targetY = y; 33 | this.actionUnitId = id; 34 | } 35 | 36 | public MoveEvent(NetworkPlayer p, float x, float y) { 37 | this.player = p; 38 | this.targetX = x; 39 | this.targetY = y; 40 | this.actionUnitId = 0; 41 | } 42 | 43 | public float getTargetX() 44 | { 45 | return targetX; 46 | } 47 | 48 | public float getTargetY() 49 | { 50 | return targetY; 51 | } 52 | 53 | public long getActionUnitId() { 54 | return this.actionUnitId; 55 | } 56 | 57 | public NetworkPlayer getPlayer() { 58 | return this.player; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/action/PingEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.action; 11 | 12 | import cn.rukkit.event.*; 13 | import cn.rukkit.game.*; 14 | 15 | public class PingEvent extends ActionEvent implements Cancellable 16 | { 17 | private static ListenerList list = new ListenerList(PingEvent.class); 18 | 19 | private String pingType; 20 | 21 | public static ListenerList getListenerList() { 22 | return list; 23 | } 24 | 25 | private NetworkPlayer player; 26 | private float targetX; 27 | private float targetY; 28 | 29 | public PingEvent(NetworkPlayer p, float x, float y, String pingType){ 30 | this.player = p; 31 | this.targetX = x; 32 | this.targetY = y; 33 | this.pingType = pingType; 34 | } 35 | 36 | public float getTargetX() 37 | { 38 | return targetX; 39 | } 40 | 41 | public float getTargetY() 42 | { 43 | return targetY; 44 | } 45 | 46 | public NetworkPlayer getPlayer() { 47 | return player; 48 | } 49 | 50 | public String getPingType() { 51 | return pingType; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/action/RallyEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.action; 11 | 12 | public class RallyEvent 13 | { 14 | } -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/action/TaskEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.action; 11 | 12 | import cn.rukkit.event.*; 13 | import cn.rukkit.event.action.*; 14 | import cn.rukkit.game.*; 15 | 16 | public class TaskEvent extends ActionEvent implements Cancellable 17 | { 18 | private static ListenerList list = new ListenerList(TaskEvent.class); 19 | 20 | public static ListenerList getListenerList() { 21 | return list; 22 | } 23 | 24 | private NetworkPlayer player; 25 | private String taskString; 26 | private long actionUnitId; 27 | private boolean isCancel = false; 28 | 29 | public TaskEvent(NetworkPlayer p, String task, long id, boolean isCancel) { 30 | this.player = p; 31 | this.taskString = task; 32 | this.actionUnitId = id; 33 | this.isCancel = isCancel; 34 | } 35 | 36 | public TaskEvent(NetworkPlayer p, String task, long id){ 37 | this.player = p; 38 | this.taskString = task; 39 | this.actionUnitId = id; 40 | } 41 | 42 | public TaskEvent(NetworkPlayer p, String task) { 43 | this.player = p; 44 | this.taskString = task; 45 | this.actionUnitId = 0; 46 | } 47 | 48 | public String getTaskString() { 49 | return this.taskString; 50 | } 51 | 52 | public long getActionUnitId() { 53 | return this.actionUnitId; 54 | } 55 | 56 | public NetworkPlayer getPlayer() { 57 | return this.player; 58 | } 59 | 60 | public boolean isCancel() { 61 | return isCancel; 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/player/OnPlayerPreRegisterEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.player; 11 | 12 | public class OnPlayerPreRegisterEvent 13 | { 14 | } -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/player/PlayerChatEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.player; 11 | import cn.rukkit.event.*; 12 | import cn.rukkit.game.*; 13 | 14 | public class PlayerChatEvent extends PlayerEvent implements Cancellable 15 | { 16 | private static ListenerList list = new ListenerList(PlayerChatEvent.class); 17 | 18 | public static ListenerList getListenerList() { 19 | return list; 20 | } 21 | 22 | private NetworkPlayer player; 23 | private String message; 24 | 25 | public PlayerChatEvent(NetworkPlayer p, String message) { 26 | this.player = p; 27 | this.message = message; 28 | } 29 | 30 | public String getMessage() { 31 | return this.message; 32 | } 33 | 34 | public NetworkPlayer getPlayer() { 35 | return this.player; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/player/PlayerEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.player; 11 | import cn.rukkit.event.*; 12 | 13 | public class PlayerEvent extends Event 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/player/PlayerJoinEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.player; 11 | 12 | import cn.rukkit.event.*; 13 | import cn.rukkit.event.player.*; 14 | import cn.rukkit.game.*; 15 | 16 | public class PlayerJoinEvent extends PlayerEvent 17 | { 18 | private static ListenerList list = new ListenerList(PlayerJoinEvent.class); 19 | 20 | public static ListenerList getListenerList() { 21 | return list; 22 | } 23 | 24 | public PlayerJoinEvent(NetworkPlayer p) { 25 | this.player = p; 26 | } 27 | 28 | private NetworkPlayer player; 29 | 30 | public NetworkPlayer getPlayer() 31 | { 32 | return player; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/player/PlayerLeftEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.player; 11 | 12 | import cn.rukkit.event.*; 13 | import cn.rukkit.event.player.*; 14 | import cn.rukkit.game.*; 15 | 16 | public class PlayerLeftEvent extends PlayerEvent 17 | { 18 | private static ListenerList list = new ListenerList(PlayerLeftEvent.class); 19 | 20 | public static ListenerList getListenerList() { 21 | return list; 22 | } 23 | 24 | public PlayerLeftEvent(NetworkPlayer p, String reason) { 25 | this.player = p; 26 | this.reason = reason; 27 | } 28 | 29 | private NetworkPlayer player; 30 | private String reason; 31 | 32 | public NetworkPlayer getPlayer() 33 | { 34 | return player; 35 | } 36 | 37 | public String getReason() { 38 | return reason; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/player/PlayerReconnectEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | /* 11 | * Copyright 2020-2022 RukkitDev Team and contributors. 12 | */ 13 | 14 | package cn.rukkit.event.player; 15 | 16 | import cn.rukkit.event.ListenerList; 17 | import cn.rukkit.game.NetworkPlayer; 18 | 19 | public class PlayerReconnectEvent extends PlayerEvent{ 20 | private static ListenerList list = new ListenerList(PlayerReconnectEvent.class); 21 | 22 | public static ListenerList getListenerList() { 23 | return list; 24 | } 25 | 26 | public PlayerReconnectEvent(NetworkPlayer p) { 27 | this.player = p; 28 | } 29 | 30 | private NetworkPlayer player; 31 | 32 | public NetworkPlayer getPlayer() 33 | { 34 | return player; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/room/RoomStartGameEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.room; 11 | 12 | import cn.rukkit.event.Event; 13 | import cn.rukkit.event.ListenerList; 14 | import cn.rukkit.network.NetworkRoom; 15 | 16 | public class RoomStartGameEvent extends Event { 17 | private static ListenerList list = new ListenerList(RoomStartGameEvent.class); 18 | 19 | public static ListenerList getListenerList() { 20 | return list; 21 | } 22 | 23 | private NetworkRoom room; 24 | 25 | public NetworkRoom getRoom() { 26 | return room; 27 | } 28 | 29 | public RoomStartGameEvent(NetworkRoom room) { 30 | this.room = room; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/room/RoomStopGameEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.event.room; 11 | 12 | import cn.rukkit.event.Event; 13 | import cn.rukkit.event.ListenerList; 14 | import cn.rukkit.network.NetworkRoom; 15 | 16 | public class RoomStopGameEvent extends Event { 17 | private static ListenerList list = new ListenerList(RoomStopGameEvent.class); 18 | 19 | public static ListenerList getListenerList() { 20 | return list; 21 | } 22 | 23 | private NetworkRoom room; 24 | 25 | public NetworkRoom getRoom() { 26 | return room; 27 | } 28 | 29 | public RoomStopGameEvent(NetworkRoom room) { 30 | this.room = room; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/server/ServerEvent.java: -------------------------------------------------------------------------------- 1 | package cn.rukkit.event.server; 2 | 3 | import cn.rukkit.event.Event; 4 | 5 | public class ServerEvent extends Event { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/event/server/ServerQuestionRespondEvent.java: -------------------------------------------------------------------------------- 1 | package cn.rukkit.event.server; 2 | 3 | import cn.rukkit.event.ListenerList; 4 | import cn.rukkit.event.player.PlayerChatEvent; 5 | import cn.rukkit.game.NetworkPlayer; 6 | 7 | public class ServerQuestionRespondEvent extends ServerEvent{ 8 | private static ListenerList list = new ListenerList(ServerQuestionRespondEvent.class); 9 | 10 | public static ListenerList getListenerList() { 11 | return list; 12 | } 13 | 14 | public ServerQuestionRespondEvent(NetworkPlayer player, int qid, String respondMessage) { 15 | this.player = player; 16 | this.qid = qid; 17 | this.respondMessage = respondMessage; 18 | } 19 | 20 | public NetworkPlayer getPlayer() { 21 | return player; 22 | } 23 | 24 | public int getQid() { 25 | return qid; 26 | } 27 | 28 | public String getRespondMessage() { 29 | return respondMessage; 30 | } 31 | 32 | private NetworkPlayer player; 33 | 34 | private int qid; 35 | 36 | private String respondMessage; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/CheckSumList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game; 11 | 12 | import org.slf4j.LoggerFactory; 13 | 14 | import java.util.ArrayList; 15 | 16 | public class CheckSumList { 17 | private ArrayList checksumItems = new ArrayList<>(); 18 | public class ChecksumItem { 19 | String description; 20 | public long checkData = 0; 21 | public long prefix = 0; 22 | public ChecksumItem(String description) { 23 | this.description = description; 24 | } 25 | 26 | public ChecksumItem(String description, long prefix) { 27 | this(description); 28 | this.prefix = prefix; 29 | } 30 | 31 | public String getDescription() { 32 | return description; 33 | } 34 | 35 | public long getCheckData() { 36 | return checkData; 37 | } 38 | 39 | public void setCheckData(long data) { 40 | this.checkData = data; 41 | } 42 | 43 | @Override 44 | public boolean equals(Object obj) { 45 | if (obj instanceof ChecksumItem item) { 46 | if (Math.abs(item.getCheckData() - getCheckData()) <= prefix) return true; 47 | else return false; 48 | } else { 49 | return false; 50 | } 51 | } 52 | } 53 | 54 | public CheckSumList() { 55 | checksumItems.add(new ChecksumItem("Unit Pos", 100000)); 56 | checksumItems.add(new ChecksumItem("Unit Dir", 100000)); 57 | checksumItems.add(new ChecksumItem("Unit Hp", 10000)); 58 | checksumItems.add(new ChecksumItem("Unit Id", 5)); 59 | checksumItems.add(new ChecksumItem("Waypoints", 5)); 60 | checksumItems.add(new ChecksumItem("Waypoints Pos", 5)); 61 | checksumItems.add(new ChecksumItem("Team Credits", 500)); 62 | checksumItems.add(new ChecksumItem("UnitPaths", 5)); 63 | checksumItems.add(new ChecksumItem("Unit Count", 10)); 64 | checksumItems.add(new ChecksumItem("Team Info", 10)); 65 | checksumItems.add(new ChecksumItem("Team 1 Credits", 500)); 66 | checksumItems.add(new ChecksumItem("Team 2 Credits", 500)); 67 | checksumItems.add(new ChecksumItem("Team 3 Credits", 500)); 68 | checksumItems.add(new ChecksumItem("Command center2", 1000)); 69 | checksumItems.add(new ChecksumItem("Command center3", 1000)); 70 | } 71 | 72 | public ArrayList getCheckList() { 73 | return checksumItems; 74 | } 75 | 76 | public void addCheckItem(ChecksumItem checksumItem) { 77 | checksumItems.add(checksumItem); 78 | } 79 | 80 | public ChecksumItem get(int index) { 81 | return checksumItems.get(index); 82 | } 83 | 84 | public boolean checkData(CheckSumList list) { 85 | int desyncCount = 0; 86 | for (int i = 0;i < checksumItems.size();i++) { 87 | if(!(checksumItems.get(i).equals(list.get(i)))) { 88 | LoggerFactory.getLogger("Checksum").warn("{} {} != {}", checksumItems.get(i).getDescription(), 89 | checksumItems.get(i).getCheckData(), list.get(i).getCheckData()); 90 | desyncCount++; 91 | } 92 | } 93 | return desyncCount == 0; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/GameActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game; 11 | 12 | public enum GameActions 13 | { 14 | MOVE,ATTACK,BUILD,REPAIR,UPLOAD,F,RECLAIM,ATTACK_MOVE,I,PATROL,PROTECT,PRODUCE 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/GlobalPlayerManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game; 11 | import cn.rukkit.*; 12 | 13 | import java.util.Arrays; 14 | //import sun.nio.ch.Net; 15 | 16 | public class GlobalPlayerManager 17 | { 18 | private int max; 19 | 20 | /** 21 | * Init player manager. 22 | * @params maxPlayer set up maxPlayer 23 | */ 24 | public GlobalPlayerManager() { 25 | } 26 | 27 | private NetworkPlayer[] players; 28 | //private static Player[] inGamePlayers = new Player[ServerProperties.maxPlayer]; 29 | 30 | 31 | 32 | /** 33 | * Get player by index. 34 | */ 35 | public NetworkPlayer get(int index){ 36 | if (index > players.length - 1) return null; 37 | return players[index]; 38 | } 39 | 40 | public NetworkPlayer getPlayerByUUID(String uuid) { 41 | for (NetworkPlayer p: players) { 42 | if (p.uuid.equals(uuid)) { 43 | return p; 44 | } 45 | } 46 | return null; 47 | } 48 | 49 | /** 50 | * get a player index. 51 | */ 52 | public int getIndex(NetworkPlayer p){ 53 | for(int i=0;i 86 | */ 87 | public T getExtraDataAs(String key, T defaultValue, Class tClass) { 88 | return (T) data.extraData.getOrDefault(key, defaultValue); 89 | } 90 | 91 | /** 92 | * 获取玩家的临时数据 93 | * @param key 94 | * @param defaultValue 95 | * @return 96 | */ 97 | public Object getTempData(String key, Object defaultValue) { 98 | return data.tempData.getOrDefault(key, defaultValue); 99 | } 100 | 101 | /** 102 | * 放入临时数据 103 | * @param key 104 | * @param value 105 | */ 106 | public void putTempData(String key, Object value) { 107 | data.tempData.put(key, value); 108 | } 109 | 110 | public void clearTempData() { 111 | data.tempData = new HashMap(); 112 | } 113 | 114 | /** 115 | * Get extra data. 116 | * @param key 117 | * @param defaultValue 118 | * @return 119 | */ 120 | public Object getExtraData(String key, Object defaultValue) { 121 | return data.extraData.getOrDefault(key, defaultValue); 122 | } 123 | 124 | /** 125 | * Put a data to player's ExtraData. 126 | * @param key 127 | * @param value 128 | */ 129 | public void putExtraData(String key, Object value) { 130 | data.extraData.put(key, value); 131 | } 132 | 133 | /** 134 | * Save player data. 135 | */ 136 | public void savePlayerData() { 137 | Yaml yaml = new Yaml(new Constructor(NetworkPlayerData.class, new LoaderOptions())); 138 | try { 139 | FileWriter writer = new FileWriter(Rukkit.getEnvPath() + "/data/player/" + uuid + ".yaml"); 140 | writer.write(yaml.dumpAs(data, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); 141 | writer.flush(); 142 | writer.close(); 143 | } catch (FileNotFoundException e) { 144 | //This should NEVER HAPPEN! 145 | } catch (IOException e) { 146 | 147 | } 148 | } 149 | 150 | public void writePlayer(DataOutputStream stream, boolean simpleMode) throws IOException { 151 | if (simpleMode) { 152 | stream.writeByte(0); 153 | stream.writeInt(ping); 154 | stream.writeBoolean(isSharingControl); 155 | stream.writeBoolean(isDisconnected || isAfk); 156 | } else { 157 | //玩家位置 158 | stream.writeByte(playerIndex); 159 | //玩家资金(毫无作用) 160 | stream.writeInt(credits); 161 | //玩家队 162 | stream.writeInt(team); 163 | 164 | stream.writeBoolean(true); 165 | 166 | if(isAdmin){ 167 | stream.writeUTF("[[[" + name + "]]]"); 168 | }else{ 169 | stream.writeUTF(name); 170 | } 171 | stream.writeBoolean(true); 172 | 173 | //enc.stream.writeBoolean(true); 174 | stream.writeInt(ping); 175 | stream.writeLong(System.currentTimeMillis()); 176 | 177 | //是否AI 178 | stream.writeBoolean(isAI); 179 | //AI难度 180 | stream.writeInt(0); 181 | 182 | //玩家队伍 183 | stream.writeInt(team); 184 | stream.writeByte(0); 185 | 186 | //分享控制 187 | stream.writeBoolean(isSharingControl); 188 | //是否掉线 189 | stream.writeBoolean(false); 190 | 191 | //是否投降 192 | stream.writeBoolean(isSurrounded); 193 | stream.writeBoolean(false); 194 | stream.writeInt(-9999); 195 | 196 | stream.writeBoolean(false); 197 | //是否房主 198 | stream.writeInt(0); 199 | 200 | // 1.15新增 201 | stream.writeBoolean(false); 202 | stream.writeBoolean(false); 203 | stream.writeBoolean(false); 204 | stream.writeBoolean(false); 205 | 206 | //color 207 | stream.writeInt(playerIndex); 208 | } 209 | } 210 | 211 | public boolean movePlayer(int index){ 212 | //If index larger then maxPlayer 213 | if (index > Rukkit.getConfig().maxPlayer) return false; 214 | PlayerManager playerGroup = room.playerManager; 215 | if (!playerGroup.get(index).isEmpty) { 216 | return false; 217 | } 218 | this.playerIndex = index; 219 | playerGroup.remove(this); 220 | playerGroup.set(index, this); 221 | return true; 222 | } 223 | 224 | public boolean moveTeam(int team){ 225 | if(team > 9 || team < 0){ 226 | return false; 227 | } else { 228 | this.team = team; 229 | } 230 | return true; 231 | } 232 | 233 | public boolean giveAdmin(int index){ 234 | NetworkPlayer player = room.playerManager.get(index); 235 | if(index < Rukkit.getConfig().maxPlayer && index >= 0 && !player.isEmpty && this.isAdmin){ 236 | player.isAdmin = true; 237 | this.isAdmin = false; 238 | return true; 239 | } 240 | return false; 241 | } 242 | 243 | public void updateServerInfo() { 244 | try { 245 | connection.handler.ctx.writeAndFlush(Packet.serverInfo(room.config, isAdmin)); 246 | } catch (IOException e) {} 247 | } 248 | 249 | public void sendTeamMessage(String message) { 250 | for (RoomConnection conn: room.connectionManager.getConnections()) { 251 | if (team == conn.player.team) { 252 | conn.sendMessage(name, 253 | LangUtil.getString("chat.teamMsg") + " " + message, 254 | playerIndex); 255 | } 256 | } 257 | } 258 | 259 | @Override 260 | public String toString() { 261 | return "NetworkPlayer{" + 262 | "name='" + name + '\'' + 263 | ", uuid='" + uuid + '\'' + 264 | ", team=" + team + 265 | ", playerIndex=" + playerIndex + 266 | ", ping=" + ping + 267 | ", isAdmin=" + isAdmin + 268 | ", isSharingControl=" + isSharingControl + 269 | ", isSurrounded=" + isSurrounded + 270 | '}'; 271 | } 272 | 273 | public boolean isNull() { 274 | return false; 275 | } 276 | 277 | public static final void initPlayerDataDir() { 278 | File dataDir = new File(Rukkit.getEnvPath() + "/data"); 279 | if (!dataDir.isDirectory()) { 280 | dataDir.delete(); 281 | dataDir.mkdir(); 282 | } 283 | File userDataDir = new File(Rukkit.getEnvPath() + "/data/player"); 284 | if (!userDataDir.isDirectory()) { 285 | userDataDir.delete(); 286 | userDataDir.mkdir(); 287 | } 288 | } 289 | 290 | public void loadPlayerData() { 291 | Logger log = LoggerFactory.getLogger("PlayerData"); 292 | log.debug("Load player infomation."); 293 | Yaml yaml = new Yaml(new Constructor(NetworkPlayerData.class, new LoaderOptions())); 294 | File dataFile = new File(Rukkit.getEnvPath() + "/data/player/" + uuid + ".yaml"); 295 | try { 296 | if (dataFile.exists()) { 297 | log.debug("Player exists.Loading..."); 298 | data = yaml.load(new FileInputStream(dataFile)); 299 | data.lastUsedName = name; 300 | data.lastConnectedTime = new Date().toString(); 301 | data.lastConnectedAddress = connection.handler.ctx.channel().remoteAddress().toString(); 302 | Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dataFile), StandardCharsets.UTF_8)); 303 | writer.write(yaml.dumpAs(data, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); 304 | writer.flush(); 305 | writer.close(); 306 | } else { 307 | log.info("New player.Creating data file..."); 308 | dataFile.createNewFile(); 309 | data = new NetworkPlayerData(); 310 | data.uuid = uuid; 311 | data.lastUsedName = name; 312 | data.lastConnectedTime = new Date().toString(); 313 | data.lastConnectedAddress = connection.handler.ctx.channel().remoteAddress().toString(); 314 | Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dataFile), StandardCharsets.UTF_8)); 315 | writer.write(yaml.dumpAs(data, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); 316 | writer.flush(); 317 | writer.close(); 318 | } 319 | } catch (FileNotFoundException ignored) { 320 | // Never happen! 321 | } catch (IOException e) { 322 | 323 | } 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/NetworkPlayerData.java: -------------------------------------------------------------------------------- 1 | package cn.rukkit.game; 2 | 3 | import java.util.HashMap; 4 | 5 | public class NetworkPlayerData { 6 | public String lastUsedName; 7 | public String uuid; 8 | public String lastConnectedTime; 9 | 10 | public String lastConnectedAddress; 11 | public HashMap extraData = new HashMap(); 12 | public HashMap tempData = new HashMap(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/PingType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game; 11 | 12 | public enum PingType { 13 | normal, 14 | attack, 15 | defend, 16 | nuke, 17 | build, 18 | upgrade, 19 | ok, 20 | no, 21 | happy, 22 | sad, 23 | retreats 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/PlayerManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game; 11 | import cn.rukkit.*; 12 | import cn.rukkit.network.NetworkRoom; 13 | 14 | import java.util.Arrays; 15 | //import sun.nio.ch.Net; 16 | 17 | public class PlayerManager 18 | { 19 | private int max; 20 | private NetworkRoom currentRoom; 21 | 22 | /** 23 | * Init player manager. 24 | * @params maxPlayer set up maxPlayer 25 | */ 26 | public PlayerManager(NetworkRoom room, int maxPlayer) { 27 | this.max = maxPlayer; 28 | currentRoom = room; 29 | reset(); 30 | } 31 | 32 | private volatile NetworkPlayer[] players; 33 | //private static Player[] inGamePlayers = new Player[ServerProperties.maxPlayer]; 34 | 35 | /** 36 | * Add a player into Array. 37 | */ 38 | public int add(NetworkPlayer p) { 39 | for(int i=0;i players.length - 1) return null; 94 | return players[index]; 95 | } 96 | 97 | public NetworkPlayer getPlayerByUUID(String uuid) { 98 | for (NetworkPlayer p: players) { 99 | if (p.uuid.equals(uuid)) { 100 | return p; 101 | } 102 | } 103 | return null; 104 | } 105 | 106 | /** 107 | * get a player index. 108 | */ 109 | public int getIndex(NetworkPlayer p){ 110 | for(int i=0;i= 5) { 40 | log.debug("" + in.readBoolean()); 41 | } 42 | if (version >= 23) { 43 | in.startBlock(true); 44 | 45 | if (version >= 54) { 46 | log.debug("{}, {}", in.readString(), in.readInt()); 47 | log.debug("{}, {}", in.readString(), in.readInt()); 48 | int basic, maxunit; 49 | log.debug("Basic={}, MaxUnit={}", basic = in.readInt(), maxunit = in.readInt()); 50 | for (int i = basic;i <= maxunit;i++) { 51 | log.debug("Unit: {} (id={})", in.readString(), in.readInt()); 52 | in.readBoolean(); 53 | if (in.readBoolean()) { 54 | log.debug("From MOD:{}", in.readString()); 55 | } 56 | in.readLong();in.readLong(); 57 | } 58 | } 59 | 60 | if (version >= 56) { 61 | /*log.debug("{}, {}", in.readString(), in.readInt()); 62 | if (in.readBoolean()) { 63 | in.readInt(); 64 | log.debug("{}, {}, {}, {}, {}, {}, {}, {}, {}" 65 | ,in.readInt(), in.readInt(), in.readBoolean(), 66 | in.readInt(), in.readInt(), in.readFloat(), 67 | in.readBoolean(), in.readBoolean(), in.readBoolean()); 68 | }*/ 69 | in.getDecodeBytes(); 70 | } 71 | 72 | log.debug("MapPath={}", in.readString()); 73 | 74 | if (version >= 73 && in.readBoolean()) { 75 | in.readStreamBytes(); 76 | } 77 | 78 | int tickTime; 79 | float mapX, mapY; 80 | 81 | log.debug("{}, {}, {}, {}", 82 | tickTime = in.readInt(), mapY = in.readFloat(), mapX = in.readFloat(), in.readFloat()); 83 | 84 | this.time = tickTime; 85 | 86 | log.debug("{}, {}", 87 | in.readInt(), in.readInt()); 88 | 89 | log.debug("Setup ended(Mark={}).", in.readShort()); 90 | 91 | /*if (in.readBoolean()) { 92 | int x = in.readInt(); 93 | int y = in.readInt(); 94 | for (int i=0;i= 86) { 102 | log.debug("{}, {}, {}, {}", 103 | in.readBoolean(), in.readBoolean(), in.readBoolean(), in.readBoolean()); 104 | } 105 | 106 | if (in.readBoolean()) { 107 | 108 | }*/ 109 | } 110 | } 111 | 112 | public void dumpToFile(File f) throws IOException { 113 | if (!f.exists()) f.createNewFile(); 114 | FileOutputStream out = new FileOutputStream(f); 115 | out.write(arr); 116 | out.flush(); 117 | } 118 | 119 | @Deprecated 120 | public void writeInjectedData(GameOutputStream out) throws IOException { 121 | GameInputStream in = new GameInputStream(arr); 122 | //GameOutputStream out = new GameOutputStream(); 123 | log.debug("{}, {}", in.readString(), in.readInt()); 124 | //out.writeString("Fuck You outputstream!!!!!!"); 125 | out.startBlock("gameSave", false); 126 | int version; 127 | //log.debug("Save Header: {}", in.readString()); 128 | out.writeString(in.readString()); // Header 129 | out.writeInt(in.readInt()); 130 | log.debug("Save Version: {}", version = in.readInt()); 131 | //version = 90; 132 | out.writeInt(version); 133 | if (version >= 5) { 134 | out.writeBoolean(in.readBoolean()); 135 | } 136 | if (version >= 23) { 137 | in.startBlock(true); 138 | out.startBlock("saveCompression", true); 139 | 140 | if (version >= 54) { 141 | out.startBlock("customUnitsBlock", false); 142 | out.startBlock("customUnits", false); 143 | int basic, maxunit; 144 | log.debug("Basic={}, MaxUnit={}", basic = in.readInt(), maxunit = in.readInt()); 145 | out.writeInt(basic); 146 | out.writeInt(maxunit); 147 | for (int i = basic;i <= maxunit;i++) { 148 | //log.debug("Unit: {} (id={})", in.readString(), in.readInt()); 149 | String name = in.readString(); 150 | log.debug("U: {}", name); 151 | out.writeString(name); 152 | out.writeInt(in.readInt()); 153 | out.writeBoolean(in.readBoolean()); 154 | if (in.readBoolean()) { 155 | out.writeBoolean(true); 156 | //log.debug("From MOD:{}", in.readString()); 157 | out.writeString(in.readString()); 158 | } 159 | out.writeLong(in.readLong()); 160 | out.writeLong(in.readLong()); 161 | } 162 | out.endBlock(); 163 | out.endBlock(); 164 | } 165 | 166 | if (version >= 56) { 167 | /*log.debug("{}, {}", in.readString(), in.readInt()); 168 | if (in.readBoolean()) { 169 | in.readInt(); 170 | log.debug("{}, {}, {}, {}, {}, {}, {}, {}, {}" 171 | ,in.readInt(), in.readInt(), in.readBoolean(), 172 | in.readInt(), in.readInt(), in.readFloat(), 173 | in.readBoolean(), in.readBoolean(), in.readBoolean()); 174 | }*/ 175 | out.startBlock("gameSetup", false); 176 | } 177 | 178 | String mapPath = in.readString(); 179 | log.debug("MapPath={}", mapPath); 180 | 181 | 182 | if (version >= 73 && in.readBoolean()) { 183 | in.readStreamBytes(); 184 | } 185 | 186 | if (Rukkit.getRoundConfig().mapType == 1) { 187 | mapPath = Rukkit.getRoundConfig().mapName + ".tmx"; 188 | out.writeString(mapPath); 189 | out.writeBoolean(true); 190 | out.writeFile(CustomMapLoader.getStreamByName(Rukkit.getRoundConfig().mapName + ".tmx")); 191 | } else { 192 | out.writeString(mapPath); 193 | out.writeBoolean(false); 194 | } 195 | 196 | // Block saveCompression 197 | byte[] cArr = new byte[in.stream.available()]; 198 | in.stream.read(cArr); 199 | out.stream.write(cArr); 200 | in.endBlock(); 201 | out.endBlock(); 202 | 203 | // Block gameSave 204 | cArr = new byte[in.stream.available()]; 205 | in.stream.read(cArr); 206 | out.stream.write(cArr); 207 | out.endBlock(); 208 | } 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/SaveManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game; 11 | import cn.rukkit.Rukkit; 12 | import cn.rukkit.game.SaveManager; 13 | import java.io.File; 14 | import java.io.FileInputStream; 15 | import java.io.FileNotFoundException; 16 | import java.io.FileOutputStream; 17 | import java.io.IOException; 18 | 19 | import cn.rukkit.network.NetworkRoom; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import cn.rukkit.network.packet.Packet; 23 | import java.io.InputStream; 24 | 25 | public class SaveManager { 26 | 27 | public SaveData lastSave; 28 | public NetworkRoom currentRoom; 29 | private Logger log; 30 | 31 | public SaveManager(NetworkRoom room) { 32 | currentRoom = room; 33 | log = LoggerFactory.getLogger("SaveManager Room #" + currentRoom.roomId); 34 | } 35 | 36 | public SaveData getDeafultSave() { 37 | return Rukkit.getDefaultSave(); 38 | } 39 | 40 | public SaveData getLastSave() { 41 | return lastSave; 42 | } 43 | 44 | public void sendDefaultSaveToAll(boolean isPullSave) throws IOException { 45 | currentRoom.broadcast(Packet.sendSave(currentRoom, getDeafultSave().arr, isPullSave)); 46 | } 47 | 48 | public void sendLastSaveToAll(boolean isPullSave) throws IOException { 49 | if (lastSave != null) { 50 | currentRoom.broadcast(Packet.sendSave(currentRoom, lastSave.arr,isPullSave)); 51 | } else { 52 | log.error("lastSave is NULL!Ignoring sendLastSaveToAll."); 53 | } 54 | } 55 | 56 | public void setLastSave(SaveData save) { 57 | lastSave = save; 58 | } 59 | 60 | 61 | public void dumpLastSave(String filename) throws FileNotFoundException, IOException { 62 | File f = new File(Rukkit.getEnvPath() + "/" + filename); 63 | if (!f.exists()) f.createNewFile(); 64 | FileOutputStream out = new FileOutputStream(f); 65 | if (lastSave != null) { 66 | out.write(lastSave.arr); 67 | out.flush(); 68 | out.close(); 69 | } else { 70 | log.error("lastSave is NULL!Ignore dump request."); 71 | //throw new NullPointerException(); 72 | } 73 | } 74 | 75 | public static SaveData readSaveFromFile(String filename) throws FileNotFoundException, IOException { 76 | FileInputStream in = new FileInputStream(filename); 77 | byte[] data = new byte[in.available()]; 78 | in.read(data); 79 | in.close(); 80 | SaveData save = new SaveData(); 81 | save.arr = data; 82 | save.time = 0; 83 | return save; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/UnitType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game; 11 | 12 | public enum UnitType{ 13 | NONE,LAND,BUILDING,AIR,WATER,HOVER,OVER_CLIFF,OVER_CLIFF_WATER 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/map/CustomMapLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game.map; 11 | 12 | import cn.rukkit.Rukkit; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import java.io.File; 17 | import java.io.FileInputStream; 18 | import java.io.FileNotFoundException; 19 | import java.util.ArrayList; 20 | 21 | public class CustomMapLoader { 22 | private static String MAP_FOLDER = Rukkit.getEnvPath() + "/maps"; 23 | private static final Logger log = LoggerFactory.getLogger(CustomMapLoader.class); 24 | 25 | public static boolean createDir(){ 26 | File folder = new File(MAP_FOLDER); 27 | folder.mkdir(); 28 | if(!folder.isDirectory()){ 29 | log.warn("Not a dir.Change a another dir..."); 30 | MAP_FOLDER = MAP_FOLDER + "_rukkit"; 31 | folder = new File(MAP_FOLDER); 32 | folder.mkdir(); 33 | if(!folder.exists() || !folder.isDirectory()){ 34 | log.error("Load failed.Stop working."); 35 | return false; 36 | } 37 | } 38 | return true; 39 | } 40 | 41 | public static ArrayList getMapList(){ 42 | File folder = new File(MAP_FOLDER); 43 | ArrayList list = new ArrayList(); 44 | for(String f: folder.list()){ 45 | String[] n = f.split("\\."); 46 | if(n[n.length - 1].equals("tmx")){ 47 | list.add(f); 48 | } 49 | } 50 | return list; 51 | } 52 | 53 | public static ArrayList getMapNameList(){ 54 | File folder = new File(MAP_FOLDER); 55 | ArrayList list = new ArrayList(); 56 | for(String f: folder.list()){ 57 | String[] n = f.split("\\."); 58 | if(n[n.length - 1].equals("tmx")){ 59 | StringBuffer sbf = new StringBuffer(); 60 | for(int i = 0;i < n.length -1;i++){ 61 | sbf.append(n[i]); 62 | } 63 | list.add(sbf.toString()); 64 | } 65 | } 66 | return list; 67 | } 68 | 69 | public static FileInputStream getStreamById(int id) throws FileNotFoundException { 70 | return new FileInputStream(getMapList().get(id)); 71 | } 72 | 73 | public static FileInputStream getStreamByName(String name) throws FileNotFoundException{ 74 | return new FileInputStream(MAP_FOLDER + "/" + name); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/map/OfficialMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game.map; 11 | 12 | public class OfficialMap 13 | { 14 | public static String[] maps = { 15 | "[p2]Beach landing (2p) [by hxyy]", 16 | "[p2]Big Island (2p)", 17 | "[p2]Dire_Straight (2p) [by uber]", 18 | "[p2]Fire Bridge (2p) [by uber]", 19 | "[p2]Hills_(2p)_[By Tstis & KPSS]", 20 | "[p2]Ice Island (2p)", 21 | "[p2]Lake (2p)", 22 | "[p2]Small_Island (2p)", 23 | "[p2]Two_cold_sides (2p)", 24 | "[p3]Hercules_(2vs1p) [by_uber]", 25 | "[p3]King of the Middle (3p)", 26 | "[p4]Depth charges (4p) [by hxyy]", 27 | "[p4]Desert (4p)", 28 | "[p4]Ice Lake (4p) [by hxyy]", 29 | "[p4]Island freeze (4p) [by hxyy]", 30 | "[p4]Lava Maze (4p)", 31 | "[p4]Lava Vortex (4p)", 32 | "[p4]Nuclear war (4p) [by hxyy]", 33 | "[p4]Magma Island (4p)", 34 | "[p4]Islands (4p)", 35 | "[p6]Shore to Shore (6p)", 36 | "[p6]Valley Pass (6p)", 37 | "[p6]Crossing (6p)", 38 | "[p8]Bridges Over Lava (8p)", 39 | "[p8]Coastline (8p) [by hxyy]", 40 | "[p8]Huge Subdivide (8p)", 41 | "[p8]Interlocked (8p)", 42 | "[p8]Interlocked Large (8p)", 43 | "[p8]Isle Ring (8p)", 44 | "[p8]Large Ice Outcrop (8p)", 45 | "[p8]Lava Bio-grid(8p)", 46 | "[p8]Lava Divide(8p)", 47 | "[p8]Many Islands (8p)", 48 | "[p8]Random Islands (8p)", 49 | "[p8]Two Sides (8p)", 50 | "[p8]Volcano (8p)", 51 | "[p8]Volcano Crater(8p)", 52 | "[p8]Tornado eye (8p) [by hxyy]", 53 | "[z;p10]Enclosed Island (10p)", 54 | "[z;p10]Kingdoms (10p) [by Vulkan]", 55 | "[z;p10]Large Lava Divide (10p)", 56 | "[z;p10]Two Sides Remake (10p)", 57 | "[z;p10]Valley Arena (10p) [by_uber]", 58 | "[z;p10]Many Islands Large (10p)", 59 | "[z;p10]Crossing Large (10p)", 60 | "[z;p10]Enclosed Island (10p)", 61 | "[z;p10]Two_Large_Islands_(10p)", 62 | "[z;p10]Wetlands (10p)"}; 63 | 64 | public static String[] mapsName = { 65 | "Beach landing (2p) [by hxyy]", 66 | "Big Island (2p)", 67 | "Dire Straight (2p) [by uber]", 68 | "Fire Bridge (2p) [by uber]", 69 | "Hills (2p) [By Tstis & KPSS]", 70 | "Ice Island (2p)", 71 | "Lake (2p)", 72 | "Small Island (2p)", 73 | "Two cold sides (2p)", 74 | "Hercules (2vs1p) [by uber]", 75 | "King of the Middle (3p)", 76 | "Depth charges (4p) [by hxyy]", 77 | "Desert (4p)", 78 | "Ice Lake (4p) [by hxyy]", 79 | "Island freeze (4p) [by hxyy]", 80 | "Lava Maze (4p)", 81 | "Lava Vortex (4p)", 82 | "Nuclear war (4p) [by hxyy]", 83 | "Magma Island (4p)", 84 | "Islands (4p)", 85 | "Shore to Shore (6p)", 86 | "Valley Pass (6p)", 87 | "Crossing (6p)", 88 | "Bridges Over Lava (8p)", 89 | "Coastline (8p) [by hxyy]", 90 | "Huge Subdivide (8p)", 91 | "Interlocked (8p)", 92 | "Interlocked Large (8p)", 93 | "Isle Ring (8p)", 94 | "Large Ice Outcrop (8p)", 95 | "Lava Bio-grid(8p)", 96 | "Lava Divide(8p)", 97 | "Many Islands (8p)", 98 | "Random Islands (8p)", 99 | "Two Sides (8p)", 100 | "Volcano (8p)", 101 | "Volcano Crater(8p)", 102 | "Tornado eye (8p) [by hxyy]", 103 | "Enclosed Island (10p)", 104 | "Kingdoms (10p) [by Vulkan]", 105 | "Large Lava Divide (10p)", 106 | "Two Sides Remake (10p)", 107 | "Valley Arena (10p) [by uber]", 108 | "Many Islands Large (10p)", 109 | "Crossing Large (10p)", 110 | "Enclosed Island (10p)", 111 | "Two Large Islands (10p)", 112 | "Wetlands (10p)"}; 113 | } 114 | 115 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/mod/Mod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game.mod; 11 | 12 | import java.util.*; 13 | 14 | public class Mod 15 | { 16 | public static class ModUnit { 17 | private String modName; 18 | private String unitName; 19 | private int unitId; 20 | 21 | public ModUnit() { 22 | super(); 23 | } 24 | 25 | public ModUnit(String unit, int id, String modname) { 26 | this.modName = modname; 27 | this.unitId = id; 28 | this.unitName = unit; 29 | } 30 | 31 | public void setModName(String modName) 32 | { 33 | this.modName = modName; 34 | } 35 | 36 | public String getModName() 37 | { 38 | return modName; 39 | } 40 | 41 | public void setUnitName(String unitName) 42 | { 43 | this.unitName = unitName; 44 | } 45 | 46 | public String getUnitName() 47 | { 48 | return unitName; 49 | } 50 | 51 | public void setUnitId(int unitId) 52 | { 53 | this.unitId = unitId; 54 | } 55 | 56 | public int getUnitId() 57 | { 58 | return unitId; 59 | } 60 | } 61 | 62 | private boolean isEnabled = true; 63 | 64 | private ArrayList unitList; 65 | 66 | public Mod(ArrayList list) { 67 | this.unitList = list; 68 | } 69 | 70 | public ArrayList getUnitList() { 71 | return unitList; 72 | }; 73 | 74 | public void setEnabled(boolean bool) { 75 | this.isEnabled = bool; 76 | } 77 | 78 | public boolean isEnabled() { 79 | return isEnabled; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/mod/ModLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game.mod; 11 | import cn.rukkit.*; 12 | import com.alibaba.fastjson2.*; 13 | import java.io.*; 14 | import java.util.*; 15 | import org.slf4j.*; 16 | 17 | public class ModLoader 18 | { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/mod/ModManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game.mod; 11 | 12 | import cn.rukkit.*; 13 | import cn.rukkit.game.mod.Mod.*; 14 | import com.alibaba.fastjson2.*; 15 | import java.io.*; 16 | import java.util.*; 17 | import org.slf4j.*; 18 | 19 | public class ModManager 20 | { 21 | private Logger log = LoggerFactory.getLogger(ModLoader.class);; 22 | private static String MOD_PATH = Rukkit.getEnvPath() + "/mods"; 23 | private HashMap loadedMods = new HashMap(); 24 | //private HashMap> loadedMods = new HashMap>(); 25 | 26 | public ModManager () { 27 | if (!createModDir()) { 28 | log.error("ModManager::Mod Exception.Server will shutdown..."); 29 | Rukkit.shutdown("Mod System fatal error."); 30 | } 31 | } 32 | 33 | private boolean createModDir() { 34 | File f = new File(MOD_PATH); 35 | if (f.exists() && f.isDirectory()) { 36 | return true; 37 | } else { 38 | //log.i("Mod folder is not exist.creating..."); 39 | f.delete(); 40 | f.mkdir(); 41 | return true; 42 | } 43 | } 44 | 45 | public void loadAllModsInDir() { 46 | File dir = new File(MOD_PATH); 47 | log.info("" + dir); 48 | for (File f: dir.listFiles()) { 49 | if (f.getName().startsWith("mod_")) { 50 | String modname = f.getName().substring(4); 51 | try 52 | { 53 | loadMod(modname, f); 54 | } 55 | catch (IOException e) 56 | { 57 | log.error("Load Mod: " + modname + " failed.", e); 58 | //log.error(e); 59 | } 60 | } 61 | } 62 | } 63 | 64 | public Mod getModByString(String jsondata) { 65 | ArrayList li = new ArrayList(); 66 | li = (ArrayList) JSON.parseArray(jsondata, ModUnit.class); 67 | return new Mod(li); 68 | } 69 | 70 | public void loadMod(String modname, File f) throws FileNotFoundException, IOException { 71 | log.info("Loading mod: " + modname); 72 | BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f))); 73 | ArrayList li = new ArrayList(); 74 | StringBuffer sbuf = new StringBuffer(); 75 | String b = null; 76 | while ((b = reader.readLine()) != null) 77 | { 78 | sbuf.append(b); 79 | } 80 | li = (ArrayList) JSON.parseArray(sbuf.toString(), ModUnit.class); 81 | Mod mod = new Mod(li); 82 | //mod.setEnabled(true); 83 | loadedMods.put(modname, mod); 84 | } 85 | 86 | public void loadModInDir(String modname) throws IOException { 87 | loadMod(modname, new File(MOD_PATH + "/mod_" + modname + ".json")); 88 | } 89 | 90 | public void loadMod(String modname, Mod mod) { 91 | loadedMods.put(modname, mod); 92 | } 93 | 94 | public void enableMod(String modname) { 95 | try{ 96 | loadedMods.getOrDefault(modname, null).setEnabled(true); 97 | } catch (NullPointerException e) { 98 | log.error(String.format("Mod '%s' is not exist.", modname), e); 99 | } 100 | } 101 | 102 | public void disableMod(String modname) { 103 | try{ 104 | loadedMods.getOrDefault(modname, null).setEnabled(false); 105 | } catch (NullPointerException e) { 106 | log.error(String.format("Mod '%s' is not exist.", modname), e); 107 | } 108 | } 109 | 110 | public void disableAllMods() { 111 | for (Map.Entry mod: loadedMods.entrySet()) { 112 | ((Mod) mod.getValue()).setEnabled(false); 113 | } 114 | } 115 | 116 | public void enableAllMods() { 117 | for (Map.Entry mod: loadedMods.entrySet()) { 118 | ((Mod) mod.getValue()).setEnabled(true); 119 | } 120 | } 121 | 122 | public HashMap getLoadedModsMap() { 123 | return loadedMods; 124 | } 125 | 126 | public Mod fetchMod(String modname){ 127 | return loadedMods.getOrDefault(modname, null); 128 | } 129 | 130 | public ArrayList fetchAllEnabledModUnits() { 131 | ArrayList list = new ArrayList(); 132 | for (Map.Entry entry: loadedMods.entrySet()) { 133 | if (((Mod)entry.getValue()).isEnabled()) { 134 | list.addAll(((Mod)entry.getValue()).getUnitList()); 135 | } 136 | } 137 | /*for(ModUnit u: list) { 138 | log.debug(String.format("Unit '%s' from '%s' (%d)", u.getModName(), u.getUnitName(), u.getUnitId())); 139 | }*/ 140 | return list; 141 | } 142 | 143 | public void loadInternalMod() throws IOException { 144 | if (fetchMod("default") != null) { 145 | log.warn("Deafult mod already loaded.Ignoring..."); 146 | return; 147 | } 148 | BufferedReader reader = new BufferedReader(new InputStreamReader(ModManager.this.getClass().getClassLoader().getResourceAsStream("mod_default.json"))); 149 | ArrayList li = new ArrayList(); 150 | StringBuffer sbuf = new StringBuffer(); 151 | String b = null; 152 | while ((b = reader.readLine()) != null) 153 | { 154 | sbuf.append(b); 155 | } 156 | li = (ArrayList) JSON.parseArray(sbuf.toString(), Mod.ModUnit.class); 157 | /*for(ModUnit u: li) { 158 | log.d(u.getModName()); 159 | }*/ 160 | Mod mod = new Mod(li); 161 | mod.setEnabled(true); 162 | loadMod("default", mod); 163 | //return li; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/game/unit/InternalUnit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.game.unit; 11 | 12 | public class InternalUnit 13 | { 14 | public static final String units[] = { 15 | "extractor", 16 | "landFactory", 17 | "airFactory", 18 | "seaFactory", 19 | "commandCenter", 20 | "turret", 21 | "antiAirTurret", 22 | "builder", 23 | "tank", 24 | "hoverTank", 25 | "artillery", 26 | "helicopter", 27 | "airShip", 28 | "gunShip", 29 | "missileShip", 30 | "gunBoat", 31 | "megaTank", 32 | "laserTank", 33 | "hovercraft", 34 | "ladybug", 35 | "battleShip", 36 | "tankDestroyer", 37 | "heavyTank", 38 | "heavyHoverTank", 39 | "laserDefence", 40 | "dropship", 41 | "tree", 42 | "repairbay", 43 | "NukeLaucher", 44 | "AntiNukeLaucher", 45 | "mammothTank", 46 | "experimentalTank", 47 | "experimentalLandFactory", 48 | "crystalResource", 49 | "wall_v", 50 | "fabricator", 51 | "attackSubmarine", 52 | "builderShip", 53 | "amphibiousJet", 54 | "supplyDepot", 55 | "experimentalHoverTank", 56 | "turret_artillery", 57 | "turret_flamethrower", 58 | "fogRevealer", 59 | "spreadingFire", 60 | "antiAirTurretT2", 61 | "turretT2", 62 | "turretT3", 63 | "damagingBorder", 64 | "zoneMarker", 65 | "editorOrBuilder", 66 | "dummyNonUnitWithTeam" 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/Connection.java.bak: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network; 11 | import cn.rukkit.game.*; 12 | import cn.rukkit.network.packet.*; 13 | import java.io.*; 14 | import java.util.*; 15 | import java.util.concurrent.*; 16 | import cn.rukkit.*; 17 | import cn.rukkit.util.*; 18 | import cn.rukkit.network.command.*; 19 | 20 | @Deprecated 21 | public class Connection { 22 | public NetworkPlayer player; 23 | public ConnectionHandler handler; 24 | public long pingTime; 25 | public int lastSyncTick = -1; 26 | private ScheduledFuture pingFuture; 27 | private ScheduledFuture teamFuture; 28 | public SaveData save; 29 | //public ChannelHandlerContext ctx; 30 | 31 | /** 32 | * Ping runnable. 33 | */ 34 | public class PingTasker implements Runnable { 35 | @Override 36 | public void run() { 37 | // TODO: Implement this method 38 | try { 39 | GameOutputStream o = new GameOutputStream(); 40 | o.writeLong(new Random().nextLong()); 41 | o.writeByte(0); 42 | Packet p = o.createPacket(108); 43 | handler.ctx.writeAndFlush(p); 44 | pingTime = System.currentTimeMillis(); 45 | } catch (IOException e) { 46 | stopPingTask(); 47 | } 48 | } 49 | } 50 | 51 | /** 52 | * TeamTask Scheduler. 53 | */ 54 | public class TeamTasker implements Runnable { 55 | @Override 56 | public void run() { 57 | // TODO: Implement this method 58 | try 59 | { 60 | updateTeamList(); 61 | } 62 | catch (IOException e) 63 | { 64 | stopTeamTask(); 65 | //log.e(e); 66 | //e.printStackTrace(); 67 | //cancel(); 68 | } 69 | } 70 | } 71 | 72 | public Connection(ConnectionHandler handler) { 73 | this.handler = handler; 74 | } 75 | 76 | public void startPingTask() { 77 | if (pingFuture != null) return; 78 | pingFuture = Rukkit.getThreadManager().schedule(new PingTasker(), 2000, 2000); 79 | } 80 | 81 | public void startTeamTask() { 82 | if (teamFuture != null) return; 83 | teamFuture = Rukkit.getThreadManager().schedule(new TeamTasker(), 1000, 1000); 84 | } 85 | 86 | public void stopPingTask() { 87 | if (pingFuture == null) return; 88 | Rukkit.getThreadManager().shutdownTask(pingFuture); 89 | pingFuture = null; 90 | } 91 | 92 | public void stopTeamTask() { 93 | if (teamFuture == null) return; 94 | Rukkit.getThreadManager().shutdownTask(teamFuture); 95 | teamFuture = null; 96 | } 97 | 98 | public void sendChat(String msg) { 99 | try { 100 | Rukkit.getConnectionManager().broadcast(Packet.chat(player.name, msg, player.playerIndex)); 101 | } catch (IOException ignored) {} 102 | } 103 | 104 | public void sendServerMessage(String msg) { 105 | try { 106 | handler.ctx.writeAndFlush(Packet.chat("SERVER", msg, -1)); 107 | } catch (IOException e) {} 108 | } 109 | 110 | public void sendMessage(String from, String msg, int team) { 111 | try { 112 | handler.ctx.writeAndFlush(Packet.chat(from, msg, team)); 113 | } catch (IOException e) {} 114 | } 115 | 116 | public void sendGameCommand(GameCommand cmd) { 117 | // If game is paused, throw everything. 118 | if (Rukkit.getGameServer().isPaused()) { 119 | return; 120 | } 121 | if (Rukkit.getConfig().useCommandQuere) { 122 | Rukkit.getGameServer().addCommand(cmd); 123 | } else { 124 | try { 125 | Rukkit.getConnectionManager().broadcast(Packet.gameCommand(Rukkit.getGameServer().getTickTime(), cmd)); 126 | } catch (IOException ignored) {} 127 | } 128 | } 129 | 130 | public void updateTeamList() throws IOException { 131 | updateTeamList(Rukkit.getGameServer().isGaming()); 132 | } 133 | 134 | public void updateTeamList(boolean simpleMode) throws IOException { 135 | GameOutputStream o = new GameOutputStream(); 136 | //log.d("Sending teamlist..."); 137 | o.writeInt(player.playerIndex); 138 | // 1.14新增 139 | o.writeBoolean(simpleMode); 140 | o.writeInt(Rukkit.getConfig().maxPlayer); //maxPlayer 141 | //1.14启用Gzip压缩 142 | GzipEncoder enc = o.getEncodeStream("teams", true); 143 | 144 | for (int i =0;i < Rukkit.getConfig().maxPlayer;i++) 145 | { 146 | NetworkPlayer playerp = Rukkit.getConnectionManager().getPlayerManager().get(i); 147 | 148 | // No-stop mode changes:Add fake players 149 | if (Rukkit.getConfig().nonStopMode) { 150 | // Always true 151 | enc.stream.writeBoolean(true); 152 | } else { 153 | enc.stream.writeBoolean(!playerp.isEmpty); 154 | } 155 | 156 | // Ignore empty player 157 | if (playerp.isEmpty) { 158 | if (!Rukkit.getConfig().nonStopMode){ 159 | continue; 160 | } 161 | } 162 | 163 | //1.14 164 | //enc.stream.writeByte(0); 165 | enc.stream.writeInt(255); 166 | playerp.writePlayer(enc.stream, simpleMode); 167 | } 168 | o.flushEncodeData(enc); 169 | 170 | o.writeInt(Rukkit.getRoundConfig().fogType); 171 | o.writeInt(GameUtils.getMoneyFormat(Rukkit.getRoundConfig().credits)); 172 | o.writeBoolean(true); 173 | //ai 174 | o.writeInt(1); 175 | // 176 | o.writeByte(4); 177 | //maxUnit 178 | o.writeInt(250); 179 | o.writeInt(250); 180 | 181 | //初始单位 182 | o.writeInt(Rukkit.getRoundConfig().startingUnits); 183 | o.writeFloat(Rukkit.getRoundConfig().income); 184 | o.writeBoolean(Rukkit.getRoundConfig().disableNuke); 185 | o.writeBoolean(false); 186 | o.writeBoolean(false); 187 | o.writeBoolean(Rukkit.getRoundConfig().sharedControl); 188 | 189 | Packet p = o.createPacket(Packet.PACKET_TEAM_LIST); 190 | 191 | handler.ctx.writeAndFlush(p); 192 | } 193 | 194 | public void kick(String reason) { 195 | try { 196 | handler.ctx.writeAndFlush(Packet.kick(reason)); 197 | } catch (IOException e) {} 198 | } 199 | 200 | public void pong() { 201 | player.ping = (int) (System.currentTimeMillis() - pingTime); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/GameInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network; 11 | 12 | import cn.rukkit.network.packet.*; 13 | import org.slf4j.LoggerFactory; 14 | 15 | import java.io.*; 16 | import java.util.*; 17 | 18 | public class GameInputStream 19 | { 20 | public ByteArrayInputStream buffer; 21 | public DataInputStream CurrentStream; 22 | public DataInputStream stream; 23 | public LinkedList blockQuere = new LinkedList(); 24 | 25 | public GameInputStream(Packet packet) { 26 | this.buffer = new ByteArrayInputStream(packet.bytes); 27 | this.stream = new DataInputStream(this.buffer); 28 | this.CurrentStream = new DataInputStream(this.buffer); 29 | } 30 | 31 | public GameInputStream(byte[] b){ 32 | this.buffer = new ByteArrayInputStream(b); 33 | this.stream = new DataInputStream(this.buffer); 34 | this.CurrentStream = new DataInputStream(this.buffer); 35 | } 36 | 37 | public GameInputStream(DataInputStream stream){ 38 | //this.buffer = new ByteArrayInputStream(b); 39 | this.stream = stream; 40 | } 41 | 42 | public DataInputStream getUnDecodeStream() throws IOException 43 | { 44 | String blockName = this.readString(); 45 | // LoggerFactory.getLogger("GameInputStream").info("BlockName: {}", blockName); 46 | byte[] bytes = readStreamBytes(); 47 | return new DataInputStream(new ByteArrayInputStream(bytes)); 48 | // TODO: Implement this method 49 | //return null; 50 | } 51 | 52 | public short readShort() throws IOException { 53 | return this.stream.readShort(); 54 | } 55 | 56 | public byte readByte() throws IOException { 57 | return this.stream.readByte(); 58 | } 59 | 60 | public boolean readBoolean() throws IOException { 61 | return this.stream.readBoolean(); 62 | } 63 | 64 | public int readInt() throws IOException { 65 | return this.stream.readInt(); 66 | } 67 | 68 | public float readFloat() throws IOException { 69 | return this.stream.readFloat(); 70 | } 71 | 72 | public long readLong() throws IOException { 73 | return this.stream.readLong(); 74 | } 75 | 76 | public String readString() throws IOException { 77 | return this.stream.readUTF(); 78 | } 79 | 80 | public byte[] readStreamBytes() throws IOException { 81 | int n2; 82 | int n3 = this.readInt(); 83 | byte[] arrby = new byte[n3]; 84 | for (int i2 = 0; i2 < n3 && (n2 = this.stream.read(arrby, i2, n3 - i2)) != -1; i2 += n2) { 85 | } 86 | return arrby; 87 | } 88 | 89 | public DataInputStream getDecodeStream() throws IOException{ 90 | String blockName = this.readString(); 91 | // LoggerFactory.getLogger("GameInputStream").info("BlockName: {}", blockName); 92 | byte[] bytes = readStreamBytes(); 93 | GzipDecoder coder = new GzipDecoder(bytes); 94 | return coder.stream; 95 | } 96 | 97 | /* 98 | * get decoded bytes. 99 | * 100 | */ 101 | public byte[] getDecodeBytes() throws IOException{ 102 | this.readString(); 103 | byte[] bytes = readStreamBytes(); 104 | return bytes; 105 | } 106 | 107 | public Enum readEnum(Class clazz) throws IOException{ 108 | int i = this.readInt(); 109 | return (Enum)clazz.getEnumConstants()[i]; 110 | } 111 | 112 | public boolean readMark() throws IOException { 113 | short mark = this.readShort(); 114 | if (mark != 12345) { 115 | LoggerFactory.getLogger("GameInputStream").error("Failed to readMark: {} != 12345", mark); 116 | return false; 117 | } else { 118 | return true; 119 | } 120 | } 121 | 122 | /* 123 | * Starts a block to read content. 124 | * Block content will buffered to List; 125 | */ 126 | public void startBlock(boolean isCompressed) throws IOException { 127 | if (isCompressed) { 128 | stream = getDecodeStream(); 129 | blockQuere.add(stream); 130 | } else { 131 | stream = getUnDecodeStream(); 132 | blockQuere.add(stream); 133 | } 134 | } 135 | 136 | /* 137 | * Ends a block content. 138 | * Delete the buffer to get the current stream. 139 | */ 140 | public void endBlock() { 141 | blockQuere.removeLast(); 142 | if (blockQuere.size() == 0) { 143 | stream = CurrentStream; 144 | } else { 145 | stream = blockQuere.getLast(); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/GameOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network; 11 | 12 | import cn.rukkit.network.packet.*; 13 | import java.io.*; 14 | import java.util.*; 15 | import java.util.zip.*; 16 | 17 | public class GameOutputStream 18 | { 19 | public ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 20 | public DataOutputStream stream = new DataOutputStream(buffer); 21 | public DataOutputStream currentStream = new DataOutputStream(buffer); 22 | public LinkedList blockQuere = new LinkedList(); 23 | 24 | private GZIPOutputStream gzipStream; 25 | 26 | private BufferedOutputStream bufferedStream; 27 | 28 | private ByteArrayOutputStream buff = new ByteArrayOutputStream(); 29 | 30 | public Packet createPacket(int type) { 31 | try { 32 | while (blockQuere.size() != 0) { 33 | endBlock(); 34 | } 35 | this.stream.flush(); 36 | this.buffer.flush(); 37 | Packet packet = new Packet(type); 38 | packet.bytes = this.buffer.toByteArray(); 39 | return packet; 40 | } catch (IOException e) { 41 | throw new RuntimeException(e); 42 | } 43 | } 44 | 45 | public void writeByte(int val) throws IOException { 46 | this.stream.writeByte(val); 47 | } 48 | 49 | public void writeBoolean(boolean val) throws IOException { 50 | this.stream.writeBoolean(val); 51 | } 52 | 53 | public void writeInt(int val) throws IOException { 54 | this.stream.writeInt(val); 55 | } 56 | 57 | public void writeFloat(float val) throws IOException { 58 | this.stream.writeFloat(val); 59 | } 60 | 61 | public void writeLong(long val) throws IOException { 62 | this.stream.writeLong(val); 63 | } 64 | 65 | public void writeShort(short val) throws IOException { 66 | this.stream.writeShort(val); 67 | } 68 | 69 | public void writeString(String val) throws IOException { 70 | this.stream.writeUTF(val); 71 | } 72 | 73 | public void write(byte[] val) throws IOException { 74 | this.stream.write(val); 75 | this.stream.flush(); 76 | } 77 | 78 | public GzipEncoder getEncodeStream(String key, boolean isGzip) throws IOException{ 79 | GzipEncoder enc = new GzipEncoder(isGzip); 80 | enc.str = key; 81 | return enc; 82 | } 83 | 84 | public void writeFile(FileInputStream stream) throws IOException{ 85 | byte[] filearr = new byte[stream.available()]; 86 | int bytesRead = 0; 87 | while (bytesRead < filearr.length) 88 | { 89 | int readIn = stream.read(filearr, bytesRead, filearr.length - bytesRead); 90 | if (readIn == -1) 91 | { 92 | break; 93 | } 94 | bytesRead += readIn; 95 | } 96 | this.stream.writeInt(filearr.length); 97 | this.stream.write(filearr); 98 | } 99 | 100 | public void flushEncodeData(GzipEncoder enc) throws IOException{ 101 | enc.flush(); 102 | this.writeString(enc.str); 103 | this.writeInt(enc.buffer.size()); 104 | enc.buffer.writeTo((OutputStream)this.stream); 105 | //stream.flush(); 106 | } 107 | 108 | public void writeEnum(Enum clazz) throws IOException { 109 | this.writeInt(clazz.ordinal()); 110 | //return (Enum)clazz.getEnumConstants()[i]; 111 | } 112 | 113 | /* 114 | * Start to writing a content block. 115 | * @params blockName a block content name 116 | */ 117 | public void startBlock(String blockName, boolean isGzip) throws IOException { 118 | GzipEncoder enc = getEncodeStream(blockName, isGzip); 119 | currentStream = stream; 120 | stream = enc.stream; 121 | blockQuere.addLast(enc); 122 | OutputStream outputStream; 123 | if (isGzip) { 124 | this.gzipStream = new GZIPOutputStream(this.buff); 125 | this.bufferedStream = new BufferedOutputStream(this.gzipStream); 126 | outputStream = this.bufferedStream; 127 | } else { 128 | outputStream = this.buff; 129 | } 130 | stream = new DataOutputStream(outputStream); 131 | } 132 | 133 | /* 134 | * End a content block. 135 | */ 136 | public void endBlock() throws IOException { 137 | if (blockQuere.size() != 0) { 138 | GzipEncoder enc = blockQuere.removeLast(); 139 | //enc.stream = stream; 140 | //enc.stream.write(stream. 141 | currentStream.writeUTF(enc.str); 142 | currentStream.writeInt(stream.size()); 143 | buff.writeTo((OutputStream)this.currentStream); 144 | buff.flush(); 145 | //detect next block 146 | if (blockQuere.size() == 0) { 147 | stream = currentStream; 148 | } else { 149 | stream = blockQuere.getLast().stream; 150 | } 151 | } 152 | 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/GlobalConnectionManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network; 11 | import io.netty.channel.group.*; 12 | import io.netty.util.concurrent.*; 13 | 14 | import java.io.IOException; 15 | import java.util.*; 16 | import cn.rukkit.game.*; 17 | import cn.rukkit.network.packet.*; 18 | import cn.rukkit.*; 19 | import org.slf4j.LoggerFactory; 20 | import org.slf4j.Logger; 21 | 22 | public class GlobalConnectionManager 23 | { 24 | List connections = new ArrayList(); 25 | private static final ChannelGroup CHANNEL_GROUP = new DefaultChannelGroup("ChannelGroups", GlobalEventExecutor.INSTANCE); 26 | 27 | //private PlayerManager playerManager; 28 | 29 | private RoomGameServer server; 30 | 31 | private Logger log = LoggerFactory.getLogger(GlobalConnectionManager.class); 32 | 33 | /** 34 | * Add a connection to list. 35 | * When player registered,this function will add it into management. 36 | */ 37 | public void add(RoomConnection connection) 38 | { 39 | connections.add(connection); 40 | //playerManager.addWithTeam(connection.player); 41 | CHANNEL_GROUP.add(connection.handler.ctx.channel()); 42 | } 43 | 44 | // @Deprecated 45 | // public void set(RoomConnection connection, int index) { 46 | // connections.add(connection); 47 | // //playerManager.set(index, connection.player); 48 | // CHANNEL_GROUP.add(connection.handler.ctx.channel()); 49 | // } 50 | 51 | /** 52 | * Broadcast a message to all connections. 53 | * @params msg Packet msg. 54 | */ 55 | public ChannelGroupFuture broadcast(Packet msg) 56 | { 57 | return CHANNEL_GROUP.writeAndFlush(msg); 58 | } 59 | 60 | /** 61 | * Broadcast a message to all connections,but using a ChannelMatcher. 62 | * @params msg Packet msg. 63 | * @params matcher ChannelMatcher. 64 | */ 65 | public ChannelGroupFuture broadcast(Packet msg, ChannelMatcher matcher) 66 | { 67 | return CHANNEL_GROUP.writeAndFlush(msg, matcher); 68 | } 69 | 70 | /** 71 | * Flush all connections. 72 | */ 73 | public ChannelGroup flush() 74 | { 75 | return CHANNEL_GROUP.flush(); 76 | } 77 | 78 | /** 79 | * Discard a connection.Auto disconnect when connection discorded. 80 | * @params connection Connection to discard. 81 | */ 82 | public boolean discard(RoomConnection connection) 83 | { 84 | connection.handler.ctx.disconnect(); 85 | connections.remove(connection); 86 | //playerManager.remove(connection.player); 87 | // Check privs. 88 | // if (connection.player.isAdmin && Rukkit.getConnectionManager().getPlayerManager().getPlayerCount() > 0) { 89 | // for (NetworkPlayer p : playerManager.getPlayerArray()) { 90 | // if (!p.isEmpty) { 91 | // p.isAdmin = true; 92 | // break; 93 | // } 94 | // } 95 | // } 96 | return CHANNEL_GROUP.remove(connection.handler.ctx.channel()); 97 | } 98 | 99 | /** 100 | * Disconnect all Connections. 101 | */ 102 | public ChannelGroupFuture disconnect() 103 | { 104 | return CHANNEL_GROUP.disconnect(); 105 | } 106 | 107 | /** 108 | * Disconnect Connections with ChannelMatcher. 109 | * @params matcher ChannelMatcher 110 | */ 111 | public ChannelGroupFuture disconnect(ChannelMatcher matcher) 112 | { 113 | return CHANNEL_GROUP.disconnect(matcher); 114 | } 115 | 116 | /** 117 | * check a connection whether in Group. 118 | * @params connection Connection need to be checked. 119 | */ 120 | public boolean contains(RoomConnection connection) 121 | { 122 | return CHANNEL_GROUP.contains(connection.handler.ctx.channel()); 123 | } 124 | 125 | /** 126 | * Return Group size. 127 | */ 128 | public int size() 129 | { 130 | return CHANNEL_GROUP.size(); 131 | } 132 | 133 | /** 134 | * Init a ConnectionManager. 135 | * @params server GameServer 136 | */ 137 | public GlobalConnectionManager(RoomGameServer server) { 138 | this.server = server; 139 | //playerManager = new PlayerManager(Rukkit.getConfig().maxPlayer); 140 | } 141 | 142 | /** 143 | * 根据名称获取玩家对象 144 | * @param name 145 | * @return 146 | */ 147 | public NetworkPlayer getPlayerByName(String name) { 148 | for (RoomConnection conn: connections) { 149 | if (conn.player.name.equals(name)) { 150 | return conn.player; 151 | } 152 | } 153 | return null; 154 | } 155 | 156 | /** 157 | * 根据UUID获取玩家对象(推荐使用,更加可靠) 158 | * @param UUID 159 | * @return 160 | */ 161 | public NetworkPlayer getPlayerByUUID(String UUID) { 162 | for (RoomConnection conn: connections) { 163 | if (conn.player.uuid.equals(UUID)) { 164 | return conn.player; 165 | } 166 | } 167 | return null; 168 | } 169 | 170 | /** 171 | * 根据UUID获取玩家对象(包括可断线重连的玩家) 172 | * 效率较低谨慎使用! 173 | * @param UUID 174 | * @return 175 | */ 176 | public NetworkPlayer getAllPlayerByUUID(String UUID) { 177 | for (NetworkRoom room: Rukkit.getRoomManager().roomList) { 178 | NetworkPlayer player; 179 | if ((player = room.playerManager.getPlayerByUUID(UUID)) != null) { 180 | return player; 181 | } 182 | } 183 | return null; 184 | } 185 | 186 | /** 187 | * Get playerManager. 188 | */ 189 | // public PlayerManager getGlobalPlayerManager() { 190 | // return playerManager; 191 | // } 192 | 193 | /** 194 | * Get connections 195 | */ 196 | public List getConnections() { 197 | return connections; 198 | } 199 | 200 | // @Deprecated 201 | // public void registerPlayer(Connection connection) { 202 | // 203 | // } 204 | 205 | // @Deprecated 206 | // public SaveData getAvailableSave() { 207 | // for (Connection conn : connections) { 208 | // if (conn.save != null) { 209 | // log.debug("Get client save, tick={}, server tick={}", conn.save.time, Rukkit.getGameServer().getTickTime()); 210 | // if (Math.abs(conn.save.time - server.getTickTime()) < Integer.MAX_VALUE) { 211 | // return conn.save; 212 | // } 213 | // } 214 | // } 215 | // return null; 216 | // } 217 | // 218 | // @Deprecated 219 | // public void clearAllSaveData() { 220 | // for (Connection conn : connections) { 221 | // conn.save = null; 222 | // } 223 | // } 224 | 225 | // @Deprecated 226 | // public void broadcastServerMessage(String msg) { 227 | // try { 228 | // broadcast(Packet.chat("SERVER", msg, -1)); 229 | // } catch (IOException ignored) {} 230 | // } 231 | 232 | public void broadcastGlobalServerMessage(String msg) { 233 | try { 234 | broadcast(Packet.chat("SERVER", msg, -1)); 235 | } catch (IOException ignored) {} 236 | } 237 | 238 | /** 239 | * Broadcast server info.(No admin trigger.) 240 | */ 241 | // @Deprecated 242 | // public void broadcastServerInfo() { 243 | // try { 244 | // broadcast(Packet.serverInfo(false)); 245 | // } catch (IOException ignored) {} 246 | // } 247 | 248 | } 249 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/GzipDecoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network; 11 | 12 | import java.io.*; 13 | import java.util.zip.*; 14 | 15 | public class GzipDecoder 16 | { 17 | public ByteArrayInputStream buffer; 18 | public DataInputStream stream; 19 | 20 | public GzipDecoder(byte[] bytes) throws IOException { 21 | this.buffer = new ByteArrayInputStream(bytes); 22 | BufferedInputStream in = new BufferedInputStream((InputStream)new GZIPInputStream((InputStream)this.buffer)); 23 | this.stream = new DataInputStream((InputStream)in); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/GzipEncoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network; 11 | 12 | import java.io.*; 13 | import java.util.zip.*; 14 | 15 | public class GzipEncoder 16 | { 17 | /* renamed from: a */ 18 | public GZIPOutputStream gzipStream; 19 | 20 | public String str; 21 | 22 | /* renamed from: b */ 23 | public BufferedOutputStream bufferedStream; 24 | 25 | /* renamed from: c */ 26 | public String f4919c; 27 | 28 | /* renamed from: d */ 29 | public ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 30 | 31 | /* renamed from: e */ 32 | public DataOutputStream stream; 33 | 34 | /* renamed from: f */ 35 | public boolean f4922f = false; 36 | 37 | /* renamed from: a */ 38 | public final void flush() throws IOException { 39 | this.buffer.flush(); 40 | if (this.bufferedStream != null) { 41 | this.bufferedStream.flush(); 42 | } 43 | if (this.gzipStream != null) { 44 | this.gzipStream.finish(); 45 | } 46 | } 47 | 48 | public GzipEncoder(boolean z) throws IOException { 49 | OutputStream outputStream; 50 | if (z) { 51 | this.gzipStream = new GZIPOutputStream(this.buffer); 52 | this.bufferedStream = new BufferedOutputStream(this.gzipStream); 53 | outputStream = this.bufferedStream; 54 | } else { 55 | outputStream = this.buffer; 56 | } 57 | this.stream = new DataOutputStream(outputStream); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/RoomConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network; 11 | 12 | import cn.rukkit.Rukkit; 13 | import cn.rukkit.game.NetworkPlayer; 14 | import cn.rukkit.game.SaveData; 15 | import cn.rukkit.network.command.GameCommand; 16 | import cn.rukkit.network.packet.Packet; 17 | import cn.rukkit.util.GameUtils; 18 | 19 | import java.io.IOError; 20 | import java.io.IOException; 21 | import java.util.Random; 22 | import java.util.concurrent.ScheduledFuture; 23 | 24 | public class RoomConnection { 25 | public NetworkPlayer player; 26 | public ConnectionHandler handler; 27 | public NetworkRoom currectRoom; 28 | public long pingTime; 29 | public int lastSyncTick = 0; 30 | public boolean checkSumSent = false; 31 | public int numberOfDesyncError = 0; 32 | 33 | private ScheduledFuture pingFuture; 34 | private ScheduledFuture teamFuture; 35 | public SaveData save; 36 | //public ChannelHandlerContext ctx; 37 | 38 | /** 39 | * 心跳包任务 40 | * Ping runnable. 41 | */ 42 | public class PingTasker implements Runnable { 43 | @Override 44 | public void run() { 45 | // TODO: Implement this method 46 | try { 47 | GameOutputStream o = new GameOutputStream(); 48 | o.writeLong(new Random().nextLong()); 49 | o.writeByte(0); 50 | Packet p = o.createPacket(108); 51 | handler.ctx.writeAndFlush(p); 52 | pingTime = System.currentTimeMillis(); 53 | } catch (IOException e) { 54 | stopPingTask(); 55 | } 56 | } 57 | } 58 | 59 | /** 60 | * 队伍列表任务 61 | * TeamTask Scheduler. 62 | */ 63 | public class TeamTasker implements Runnable { 64 | @Override 65 | public void run() { 66 | // TODO: Implement this method 67 | try 68 | { 69 | updateTeamList(); 70 | } 71 | catch (IOException e) 72 | { 73 | stopTeamTask(); 74 | //log.e(e); 75 | //e.printStackTrace(); 76 | //cancel(); 77 | } 78 | } 79 | } 80 | 81 | public RoomConnection(ConnectionHandler handler, NetworkRoom currectRoom) { 82 | this.handler = handler; 83 | this.currectRoom = currectRoom; 84 | } 85 | 86 | public void startPingTask() { 87 | if (pingFuture != null) return; 88 | pingFuture = Rukkit.getThreadManager().schedule(new PingTasker(), 2000, 2000); 89 | } 90 | 91 | public void startTeamTask() { 92 | if (teamFuture != null) return; 93 | teamFuture = Rukkit.getThreadManager().schedule(new TeamTasker(), 1000, 1000); 94 | } 95 | 96 | public void stopPingTask() { 97 | if (pingFuture == null) return; 98 | Rukkit.getThreadManager().shutdownTask(pingFuture); 99 | pingFuture = null; 100 | } 101 | 102 | public void stopTeamTask() { 103 | if (teamFuture == null) return; 104 | Rukkit.getThreadManager().shutdownTask(teamFuture); 105 | teamFuture = null; 106 | } 107 | 108 | public void doChecksum() { 109 | try { 110 | handler.ctx.writeAndFlush(Packet.syncCheckSum(lastSyncTick)); 111 | } catch (IOException ignored) {} 112 | } 113 | 114 | /** 115 | * 发送公开聊天 116 | * @param msg 117 | */ 118 | public void sendChat(String msg) { 119 | try { 120 | currectRoom.connectionManager.broadcast(Packet.chat(player.name, msg, player.playerIndex)); 121 | } catch (IOException ignored) {} 122 | } 123 | 124 | /** 125 | * 发送服务器信息 ([SERVER]) 126 | * @param msg 127 | */ 128 | public void sendServerMessage(String msg) { 129 | try { 130 | handler.ctx.writeAndFlush(Packet.chat("SERVER", msg, -1)); 131 | } catch (IOException e) {} 132 | } 133 | 134 | /** 135 | * 发送玩家信息 136 | * @param from 来源玩家名 137 | * @param msg 信息 138 | * @param team 队伍 139 | */ 140 | public void sendMessage(String from, String msg, int team) { 141 | try { 142 | handler.ctx.writeAndFlush(Packet.chat(from, msg, team)); 143 | } catch (IOException e) {} 144 | } 145 | 146 | /** 147 | * 发送游戏指令 148 | * @param cmd GameCommand实例. 149 | */ 150 | public void sendGameCommand(GameCommand cmd) { 151 | // If game is paused, throw everything. 152 | if (currectRoom.isPaused()) { 153 | return; 154 | } 155 | if (Rukkit.getConfig().useCommandQuere) { 156 | currectRoom.addCommand(cmd); 157 | } else { 158 | try { 159 | currectRoom.connectionManager.broadcast(Packet.gameCommand(currectRoom.getTickTime(), cmd)); 160 | } catch (IOException ignored) {} 161 | } 162 | } 163 | 164 | public void updateTeamList() throws IOException { 165 | updateTeamList(currectRoom.isGaming()); 166 | } 167 | 168 | /** 169 | * 更新队伍列表。 170 | * @param simpleMode 简单模式(1.14+).减少网络数据通信。 171 | * @throws IOException 172 | */ 173 | public void updateTeamList(boolean simpleMode) throws IOException { 174 | GameOutputStream o = new GameOutputStream(); 175 | //log.d("Sending teamlist..."); 176 | o.writeInt(player.playerIndex); 177 | // 1.14新增 178 | o.writeBoolean(simpleMode); 179 | o.writeInt(Rukkit.getConfig().maxPlayer); //maxPlayer 180 | //1.14启用Gzip压缩 181 | GzipEncoder enc = o.getEncodeStream("teams", true); 182 | 183 | for (int i =0;i < Rukkit.getConfig().maxPlayer;i++) 184 | { 185 | NetworkPlayer playerp = currectRoom.playerManager.get(i); 186 | 187 | enc.stream.writeBoolean(!playerp.isEmpty); 188 | 189 | // Ignore empty player 190 | if (playerp.isEmpty) { 191 | continue; 192 | } 193 | 194 | //1.14 195 | //enc.stream.writeByte(0); 196 | 197 | enc.stream.writeInt(255); 198 | playerp.writePlayer(enc.stream, simpleMode); 199 | } 200 | o.flushEncodeData(enc); 201 | 202 | o.writeInt(currectRoom.config.fogType); 203 | o.writeInt(GameUtils.getMoneyFormat(currectRoom.config.credits)); 204 | o.writeBoolean(true); 205 | //ai 206 | o.writeInt(1); 207 | // 208 | o.writeByte(4); 209 | //maxUnit 210 | o.writeInt(250); 211 | o.writeInt(250); 212 | 213 | //初始单位 214 | o.writeInt(currectRoom.config.startingUnits); 215 | o.writeFloat(currectRoom.config.income); 216 | o.writeBoolean(currectRoom.config.disableNuke); 217 | o.writeBoolean(false); 218 | o.writeBoolean(false); 219 | o.writeBoolean(currectRoom.config.sharedControl); 220 | 221 | Packet p = o.createPacket(Packet.PACKET_TEAM_LIST); 222 | 223 | handler.ctx.writeAndFlush(p); 224 | } 225 | 226 | /** 227 | * 踢出玩家 228 | * @param reason 踢出理由 229 | */ 230 | public void kick(String reason) { 231 | try { 232 | handler.ctx.writeAndFlush(Packet.kick(reason)); 233 | } catch (IOException e) {} 234 | } 235 | 236 | /** 237 | * 心跳包返回 238 | */ 239 | public void pong() { 240 | player.ping = (int) (System.currentTimeMillis() - pingTime); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/RoomConnectionManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network; 11 | 12 | import cn.rukkit.Rukkit; 13 | import cn.rukkit.game.NetworkPlayer; 14 | import cn.rukkit.game.PlayerManager; 15 | import cn.rukkit.game.SaveData; 16 | import cn.rukkit.network.packet.Packet; 17 | import io.netty.channel.group.ChannelGroup; 18 | import io.netty.channel.group.ChannelGroupFuture; 19 | import io.netty.channel.group.ChannelMatcher; 20 | import io.netty.channel.group.DefaultChannelGroup; 21 | import io.netty.util.concurrent.GlobalEventExecutor; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import java.io.IOException; 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | public class RoomConnectionManager { 30 | private final NetworkRoom room; 31 | volatile List connections = new ArrayList(); 32 | private ChannelGroup CHANNEL_GROUP; 33 | 34 | private PlayerManager playerManager; 35 | 36 | private RoomGameServer server; 37 | 38 | private Logger log; 39 | 40 | /** 41 | * Add a connection to list. 42 | * When player registered,this function will add it into management. 43 | */ 44 | public void add(RoomConnection connection) { 45 | connections.add(connection); 46 | playerManager.addWithTeam(connection.player); 47 | CHANNEL_GROUP.add(connection.handler.ctx.channel()); 48 | } 49 | 50 | public void set(RoomConnection connection, int index) { 51 | connections.add(connection); 52 | playerManager.set(index, connection.player); 53 | CHANNEL_GROUP.add(connection.handler.ctx.channel()); 54 | } 55 | 56 | /** 57 | * Broadcast a message to all connections. 58 | * 59 | * @params msg Packet msg. 60 | */ 61 | public ChannelGroupFuture broadcast(Packet msg) { 62 | return CHANNEL_GROUP.writeAndFlush(msg); 63 | } 64 | 65 | /** 66 | * Broadcast a message to all connections,but using a ChannelMatcher. 67 | * 68 | * @params msg Packet msg. 69 | * @params matcher ChannelMatcher. 70 | */ 71 | public ChannelGroupFuture broadcast(Packet msg, ChannelMatcher matcher) { 72 | return CHANNEL_GROUP.writeAndFlush(msg, matcher); 73 | } 74 | 75 | /** 76 | * Flush all connections. 77 | */ 78 | public ChannelGroup flush() { 79 | return CHANNEL_GROUP.flush(); 80 | } 81 | 82 | /** 83 | * Discard a connection.Auto disconnect when connection discorded. 84 | * 85 | * @params connection Connection to discard. 86 | */ 87 | public boolean discard(RoomConnection connection) { 88 | connection.handler.ctx.disconnect(); 89 | connections.remove(connection); 90 | playerManager.remove(connection.player); 91 | // Check privs. 92 | if (connection.player.isAdmin && playerManager.getPlayerCount() > 0) { 93 | for (NetworkPlayer p : playerManager.getPlayerArray()) { 94 | if (!p.isEmpty) { 95 | p.isAdmin = true; 96 | try { 97 | p.getConnection().handler.ctx.writeAndFlush(Packet.serverInfo(room.config, true)); 98 | } catch (IOException ignored) {} 99 | break; 100 | } 101 | } 102 | } 103 | return CHANNEL_GROUP.remove(connection.handler.ctx.channel()); 104 | } 105 | 106 | /** 107 | * Disconnect all Connections. 108 | */ 109 | public ChannelGroupFuture disconnect() { 110 | return CHANNEL_GROUP.disconnect(); 111 | } 112 | 113 | /** 114 | * Disconnect Connections with ChannelMatcher. 115 | * 116 | * @params matcher ChannelMatcher 117 | */ 118 | public ChannelGroupFuture disconnect(ChannelMatcher matcher) { 119 | return CHANNEL_GROUP.disconnect(matcher); 120 | } 121 | 122 | /** 123 | * check a connection whether in Group. 124 | * 125 | * @params connection need to be checked. 126 | */ 127 | public boolean contains(RoomConnection connection) { 128 | return CHANNEL_GROUP.contains(connection.handler.ctx.channel()); 129 | } 130 | 131 | /** 132 | * Return Group size. 133 | */ 134 | public int size() { 135 | return CHANNEL_GROUP.size(); 136 | } 137 | 138 | /** 139 | * Init a ConnectionManager. 140 | * 141 | * @params server GameServer 142 | */ 143 | public RoomConnectionManager(NetworkRoom room) { 144 | this.room = room; 145 | playerManager = room.playerManager; 146 | log = LoggerFactory.getLogger("RoomConnectionManager #" + room.roomId); 147 | CHANNEL_GROUP = new DefaultChannelGroup("ChannelGroups" + room.roomId, GlobalEventExecutor.INSTANCE); 148 | } 149 | 150 | public void getPlayerAsList() { 151 | 152 | } 153 | 154 | /** 155 | * Get connections 156 | */ 157 | public List getConnections() { 158 | return connections; 159 | } 160 | 161 | // public void registerPlayer(Connection connection) { 162 | // 163 | // } 164 | 165 | public SaveData getAvailableSave() { 166 | for (RoomConnection conn : connections) { 167 | if (conn.save != null) { 168 | log.debug("Get client save, tick={}, server tick={}", conn.save.time, room.getCurrentStep()); 169 | if (Math.abs(conn.save.time - room.getCurrentStep()) < Integer.MAX_VALUE) { 170 | return conn.save; 171 | } 172 | } 173 | } 174 | return null; 175 | } 176 | 177 | public void clearAllSaveData() { 178 | for (RoomConnection conn : connections) { 179 | conn.save = null; 180 | } 181 | } 182 | 183 | public void broadcastServerMessage(String msg) { 184 | try { 185 | broadcast(Packet.chat("SERVER", msg, -1)); 186 | } catch (IOException ignored) { 187 | } 188 | } 189 | 190 | public void broadcastGlobalServerMessage(String msg) { 191 | try { 192 | broadcast(Packet.chat("SERVER", msg, -1)); 193 | } catch (IOException ignored) { 194 | } 195 | } 196 | 197 | /** 198 | * Broadcast server info.(No admin trigger.) 199 | */ 200 | public void broadcastServerInfo() { 201 | try { 202 | broadcast(Packet.serverInfo(room.config, false)); 203 | } catch (IOException ignored) { 204 | } 205 | } 206 | 207 | } 208 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/RoomGameServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network; 11 | 12 | import cn.rukkit.Rukkit; 13 | import cn.rukkit.network.packet.PacketDecoder; 14 | import cn.rukkit.network.packet.PacketEncoder; 15 | import io.netty.bootstrap.ServerBootstrap; 16 | import io.netty.channel.ChannelFuture; 17 | import io.netty.channel.ChannelInitializer; 18 | import io.netty.channel.ChannelOption; 19 | import io.netty.channel.nio.NioEventLoopGroup; 20 | import io.netty.channel.socket.SocketChannel; 21 | import io.netty.channel.socket.nio.NioServerSocketChannel; 22 | import io.netty.handler.logging.LogLevel; 23 | import io.netty.handler.logging.LoggingHandler; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | public class RoomGameServer { 28 | private NioEventLoopGroup bossGroup; 29 | private NioEventLoopGroup workerGroup; 30 | private ChannelFuture serverFuture; 31 | 32 | private Logger log = LoggerFactory.getLogger("GameServer"); 33 | 34 | /** 35 | * Start a Server. 36 | */ 37 | public void action(final long time) throws InterruptedException { 38 | // 用来接收进来的连接 39 | bossGroup = new NioEventLoopGroup(); 40 | // 用来处理已经被接收的连接,一旦bossGroup接收到连接,就会把连接信息注册到workerGroup上 41 | workerGroup = new NioEventLoopGroup(); 42 | try { 43 | ServerBootstrap sbs = new ServerBootstrap(); 44 | sbs.group(bossGroup, workerGroup) 45 | .channel(NioServerSocketChannel.class) 46 | .option(ChannelOption.SO_BACKLOG, 128) 47 | .childOption(ChannelOption.SO_KEEPALIVE, true) 48 | //.handler(new LoggingHandler(log)) 49 | .handler(new LoggingHandler(log.getName(), LogLevel.DEBUG)) 50 | .childHandler(new ChannelInitializer(){ 51 | 52 | @Override 53 | protected void initChannel(SocketChannel p1) throws Exception { 54 | // TODO: Implement this method 55 | p1.pipeline().addLast(new PacketDecoder()); 56 | p1.pipeline().addLast(new PacketEncoder()).addLast(new ConnectionHandler()); 57 | } 58 | }); 59 | //System.out.println("-Server started!"); 60 | new Thread(new Runnable() { 61 | @Override 62 | public void run() { 63 | log.info("Done! (" + (System.currentTimeMillis() - time) + "ms)"); 64 | Rukkit.setStarted(true); 65 | // TODO: Implement this method 66 | } 67 | }).start(); 68 | serverFuture = sbs.bind(Rukkit.getConfig().serverPort).sync(); 69 | serverFuture.channel().closeFuture().sync(); 70 | } catch (Exception e) { 71 | log.error("A error occurred: ", e); 72 | Rukkit.shutdown(e.getMessage()); 73 | bossGroup.shutdownGracefully(); 74 | workerGroup.shutdownGracefully(); 75 | return; 76 | } finally { 77 | bossGroup.shutdownGracefully(); 78 | workerGroup.shutdownGracefully(); 79 | } 80 | } 81 | 82 | public void stopServer() { 83 | workerGroup.shutdownGracefully(); 84 | bossGroup.shutdownGracefully(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/RoomManager.java: -------------------------------------------------------------------------------- 1 | package cn.rukkit.network; 2 | 3 | import cn.rukkit.Rukkit; 4 | import cn.rukkit.config.RoundConfig; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class RoomManager { 10 | public List roomList; 11 | public RoomManager(RoundConfig defaultConfig, int maxRoom) { 12 | roomList = new ArrayList(maxRoom); 13 | resetAllRooms(); 14 | } 15 | 16 | public void addConnection(RoomConnection conn, int roomId) { 17 | 18 | } 19 | 20 | public void addConnection(RoomConnection conn) { 21 | 22 | } 23 | 24 | /** 25 | * 获取当前的默认房间(id = 0). 26 | * @return 房间实例 27 | */ 28 | public NetworkRoom getDefaultRoom() { 29 | return roomList.get(0); 30 | } 31 | 32 | /** 33 | * 获取房间。根据房间id进入。 34 | * @param index 35 | * @return 36 | */ 37 | public NetworkRoom getRoom(int index) { 38 | return roomList.get(index); 39 | } 40 | 41 | /** 42 | * 获得当前可用的房间。 43 | * @return NetworkRoom实例. 44 | */ 45 | public NetworkRoom getAvailableRoom() { 46 | for (NetworkRoom room: roomList) { 47 | if (room.playerManager.getPlayerCount() < room.playerManager.getMaxPlayer()){ 48 | if (!room.isGaming()) { 49 | return room; 50 | } 51 | } 52 | } 53 | return null; 54 | } 55 | 56 | /** 57 | * Reset all Rooms. 58 | * 重置所有房间。重置后房间数是rukkit.yml处的 maxRoom 59 | */ 60 | public void resetAllRooms() { 61 | for (NetworkRoom room: roomList) { 62 | if (room != null) { 63 | room.connectionManager.broadcastServerMessage("Room reset."); 64 | room.connectionManager.disconnect(); 65 | room.discard(); 66 | roomList.remove(room); 67 | } 68 | } 69 | for (int id = 0;id < Rukkit.getConfig().maxRoom;id ++){ 70 | roomList.add(new NetworkRoom(id)); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/packet/PacketDecoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network.packet; 11 | 12 | import io.netty.buffer.*; 13 | import io.netty.channel.*; 14 | import io.netty.handler.codec.*; 15 | import java.util.*; 16 | import org.slf4j.*; 17 | 18 | public class PacketDecoder extends ByteToMessageDecoder 19 | { 20 | 21 | private static final int HEAD_SIZE = 8; 22 | private static Logger log = LoggerFactory.getLogger(PacketDecoder.class); 23 | 24 | @Override 25 | protected void decode(ChannelHandlerContext p1, ByteBuf p2, List p3) throws Exception 26 | { 27 | p2.markReaderIndex(); 28 | //log.(p1.name()); 29 | 30 | //log.d("got!"); 31 | 32 | // 判断是否可读 33 | if(!p2.isReadable()){ 34 | p2.resetReaderIndex(); 35 | log.debug("unreadable!"); 36 | return; 37 | } 38 | 39 | // 判断请求大小 40 | if(p2.readableBytes() < HEAD_SIZE){ 41 | p2.resetReaderIndex(); 42 | //log.d("too small!"); 43 | return; 44 | } 45 | 46 | // 拼包逻辑 47 | int length = p2.readInt(); 48 | int type = p2.readInt(); 49 | //log.d(length); 50 | int readableBytes = p2.readableBytes(); 51 | //log.d(readableBytes); 52 | //如果可读字节不足 53 | if(readableBytes < length){ 54 | p2.resetReaderIndex(); 55 | //log.d("not enough!"); 56 | return; 57 | } 58 | 59 | byte bytes[] = new byte[length]; 60 | p2.readBytes(bytes); 61 | 62 | Packet p = new Packet(type); 63 | p.bytes = bytes; 64 | log.trace("Got the packet. (type=" + p.type + " size=" + p.bytes.length + ")"); 65 | 66 | p3.add(p); 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/network/packet/PacketEncoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.network.packet; 11 | 12 | import io.netty.buffer.*; 13 | import io.netty.channel.*; 14 | import io.netty.handler.codec.*; 15 | import org.slf4j.*; 16 | 17 | 18 | public class PacketEncoder extends MessageToByteEncoder 19 | { 20 | 21 | Logger log = LoggerFactory.getLogger(PacketEncoder.class); 22 | @Override 23 | protected void encode(ChannelHandlerContext p1, Packet p2, ByteBuf p3) throws Exception 24 | { 25 | // TODO: Implement this method 26 | //log.setTag(p1.name()); 27 | if (p2.type != 10) { 28 | log.trace("Sending packets... (type=" + p2.type + " size=" + p2.bytes.length + ")"); 29 | } else { 30 | if (p2.bytes.length > 20) { 31 | log.trace("Sending game packets... (type=" + p2.type + " size=" + p2.bytes.length + ")"); 32 | } 33 | } 34 | p3.writeInt(p2.bytes.length); 35 | p3.writeInt(p2.type); 36 | p3.writeBytes(p2.bytes); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/plugin/Plugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.plugin; 11 | 12 | import cn.rukkit.event.EventListenerContainer; 13 | 14 | import java.util.ArrayList; 15 | 16 | public interface Plugin 17 | { 18 | public void onLoad(); 19 | public void onEnable(); 20 | public void onDisable(); 21 | public void onStart(); 22 | public void onDone(); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/plugin/PluginConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.plugin; 11 | import cn.rukkit.config.*; 12 | 13 | public class PluginConfig extends BaseConfig 14 | { 15 | public String author; 16 | public String name; 17 | public String id; 18 | public String version; 19 | public String apiVersion; 20 | public String pluginClass; 21 | public String main; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/plugin/RukkitPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.plugin; 11 | import cn.rukkit.*; 12 | import java.io.*; 13 | import java.util.ArrayList; 14 | 15 | import cn.rukkit.event.EventListener; 16 | import cn.rukkit.event.EventListenerContainer; 17 | import org.slf4j.*; 18 | import org.yaml.snakeyaml.*; 19 | import cn.rukkit.config.*; 20 | import org.yaml.snakeyaml.nodes.Tag; 21 | 22 | public abstract class RukkitPlugin implements Plugin 23 | { 24 | public PluginConfig config; 25 | protected ArrayList listeners = new ArrayList(); 26 | 27 | private boolean isEnabled; 28 | 29 | public RukkitPlugin() {} 30 | public final void setEnabled(boolean isEnabled) { 31 | this.isEnabled = isEnabled; 32 | if (isEnabled) { 33 | onEnable(); 34 | } else { 35 | onDisable(); 36 | } 37 | } 38 | 39 | public final boolean isEnabled() { 40 | return isEnabled; 41 | } 42 | 43 | public final Logger getLogger() { 44 | return LoggerFactory.getLogger(this.getPluginId() + "-" + this.getClass()); 45 | } 46 | 47 | public final File getConfigFile(String config) 48 | { 49 | File configDir = new File(Rukkit.getEnvPath() + "/plugins/"+ this.config.name); 50 | 51 | if (configDir.isFile()) { 52 | configDir.delete(); 53 | } 54 | 55 | if (!configDir.exists()) { 56 | configDir.mkdir(); 57 | } 58 | 59 | File configFile = new File(configDir + "/" + config + ".yml"); 60 | if (configFile.isDirectory()) { 61 | configFile.delete(); 62 | } 63 | 64 | if (!configFile.exists()) { 65 | try 66 | { 67 | configFile.createNewFile(); 68 | } 69 | catch (IOException e) 70 | { 71 | e.printStackTrace(); 72 | } 73 | } 74 | 75 | return configFile; 76 | } 77 | 78 | public final T getConfig(File file, Class cls) throws FileNotFoundException { 79 | Yaml yaml = new Yaml(); 80 | return yaml.loadAs((new FileInputStream(file)), cls); 81 | } 82 | 83 | public final void saveConfig(File file, Object cls) throws IOException { 84 | Yaml yaml = new Yaml(); 85 | FileWriter writer = new FileWriter(file); 86 | writer.write(yaml.dumpAs(cls, Tag.MAP, DumperOptions.FlowStyle.BLOCK)); 87 | writer.flush(); 88 | writer.close(); 89 | } 90 | 91 | public String getPluginId() { 92 | return config.id; 93 | } 94 | 95 | public PluginManager getPluginManager() { 96 | return Rukkit.getPluginManager(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/plugin/internal/BasePlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | /* 11 | * Copyright 2020-2022 RukkitDev Team and contributors. 12 | */ 13 | 14 | package cn.rukkit.plugin.internal; 15 | 16 | import cn.rukkit.Rukkit; 17 | import cn.rukkit.event.EventHandler; 18 | import cn.rukkit.event.EventListener; 19 | import cn.rukkit.event.player.PlayerChatEvent; 20 | import cn.rukkit.event.player.PlayerJoinEvent; 21 | import cn.rukkit.event.player.PlayerLeftEvent; 22 | import cn.rukkit.event.player.PlayerReconnectEvent; 23 | import cn.rukkit.network.RoomConnection; 24 | import cn.rukkit.plugin.PluginConfig; 25 | import cn.rukkit.util.LangUtil; 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | 29 | import java.text.MessageFormat; 30 | 31 | public class BasePlugin extends InternalRukkitPlugin implements EventListener { 32 | 33 | private Logger log = LoggerFactory.getLogger("Rukkit"); 34 | 35 | 36 | @EventHandler 37 | public void onPlayerJoinTip(PlayerJoinEvent event) { 38 | event.getPlayer().getRoom().connectionManager.broadcastServerMessage(MessageFormat.format(LangUtil.getString("rukkit.playerJoin"), event.getPlayer().name)); 39 | LoggerFactory.getLogger("Room #" + event.getPlayer().getRoom().roomId).info("Player {} joined!", event.getPlayer().name); 40 | } 41 | 42 | @EventHandler 43 | public void onPlayerLeaveTip(PlayerLeftEvent event) { 44 | event.getPlayer().getRoom().connectionManager.broadcastServerMessage(MessageFormat.format(LangUtil.getString("rukkit.playerLeft"), event.getPlayer().name, event.getReason())); 45 | if (event.getPlayer().getRoom().isGaming()) { 46 | event.getPlayer().sendTeamMessage(LangUtil.getString("rukkit.playerSharingControlDueDisconnected")); 47 | } 48 | LoggerFactory.getLogger("Room #" + event.getPlayer().getRoom().roomId).info("Player {} left!({})", event.getPlayer().name, event.getReason()); 49 | event.getPlayer().savePlayerData(); 50 | } 51 | 52 | @EventHandler 53 | public void onPlayerChatInfo(PlayerChatEvent event) { 54 | LoggerFactory.getLogger("Room #" + event.getPlayer().getRoom().roomId).info("[{}] {}", event.getPlayer().name, event.getMessage()); 55 | } 56 | 57 | @EventHandler 58 | public void onPlayerReconnected(PlayerReconnectEvent event) { 59 | event.getPlayer().getRoom().connectionManager.broadcastServerMessage(MessageFormat.format(LangUtil.getString("rukkit.playerReconnect"), event.getPlayer().name)); 60 | LoggerFactory.getLogger("Room #" + event.getPlayer().getRoom().roomId).info("Player {} reconnected!", event.getPlayer().name); 61 | } 62 | 63 | @Override 64 | public void onLoad() { 65 | getLogger().info("BasePlugin::Load"); 66 | getPluginManager().registerEventListener(this, this); 67 | } 68 | 69 | @Override 70 | public void onEnable() { 71 | 72 | } 73 | 74 | @Override 75 | public void onDisable() { 76 | getLogger().info("PlayerManager::Saving Player Data..."); 77 | } 78 | 79 | @Override 80 | public void onStart() { 81 | 82 | } 83 | 84 | @Override 85 | public void onDone() { 86 | 87 | } 88 | 89 | @Override 90 | public void loadConfig() { 91 | config = new PluginConfig(); 92 | config.name = "Basic Game Plugin"; 93 | config.author = "rukkit"; 94 | config.version = Rukkit.RUKKIT_VERSION; 95 | config.id = "base-plugin"; 96 | config.pluginClass = "cn.rukkit.plugin.internal.BasePlugin"; 97 | config.apiVersion = Rukkit.PLUGIN_API_VERSION; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/plugin/internal/InternalRukkitPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.plugin.internal; 11 | import cn.rukkit.plugin.*; 12 | 13 | abstract class InternalRukkitPlugin extends RukkitPlugin 14 | { 15 | public InternalRukkitPlugin() { 16 | loadConfig(); 17 | } 18 | 19 | public abstract void loadConfig(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/plugin/internal/ScriptPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.plugin.internal; 11 | import java.util.TimerTask; 12 | 13 | public class ScriptPlugin 14 | { 15 | public void test() { 16 | new TimerTask() { 17 | @Override 18 | public void run() { 19 | } 20 | }; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/plugin/internal/TestPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.plugin.internal; 11 | 12 | import cn.rukkit.Rukkit; 13 | import cn.rukkit.command.ChatCommand; 14 | import cn.rukkit.command.ChatCommandListener; 15 | import cn.rukkit.event.EventHandler; 16 | import cn.rukkit.event.EventListener; 17 | import cn.rukkit.event.action.PingEvent; 18 | import cn.rukkit.game.NetworkPlayer; 19 | import cn.rukkit.network.RoomConnection; 20 | import cn.rukkit.network.packet.Packet; 21 | import cn.rukkit.plugin.PluginConfig; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | 26 | public class TestPlugin extends InternalRukkitPlugin implements EventListener { 27 | 28 | TestPluginConfig testConfig = new TestPluginConfig(); 29 | 30 | class TestSyncCallback implements ChatCommandListener { 31 | @Override 32 | public boolean onSend(RoomConnection con, String[] args) { 33 | con.currectRoom.syncGame(); 34 | return false; 35 | } 36 | } 37 | 38 | class SummonCallback implements ChatCommandListener { 39 | @Override 40 | public boolean onSend(RoomConnection con, String[] args) { 41 | if (!con.currectRoom.isGaming()) { 42 | con.sendServerMessage("游戏未开始!"); 43 | return false; 44 | } 45 | if (args.length >= 1) { 46 | long time = (long) con.player.getTempData("lastSummonTime", 0L); 47 | long currentTime = System.currentTimeMillis(); 48 | if (currentTime - time < testConfig.cd) { 49 | con.player.getConnection().sendServerMessage("请等待" + ((currentTime - time) / 1000) + "秒"); 50 | return false; 51 | } 52 | con.sendServerMessage("请PING一个位置"); 53 | con.player.putTempData("spawnUnit", args[0]); 54 | con.player.putTempData("isSpawnTriggered", true); 55 | con.player.putTempData("lastSummonTime", System.currentTimeMillis()); 56 | } 57 | return false; 58 | } 59 | } 60 | 61 | @EventHandler 62 | public void onPing(PingEvent event) { 63 | NetworkPlayer player = event.getPlayer(); 64 | boolean isTriggered = (boolean) player.getTempData("isSpawnTriggered", false); 65 | String unit = (String) event.getPlayer().getTempData("spawnUnit", "tank"); 66 | if (isTriggered) { 67 | if (unit.equals("editorOrBuilder")) { 68 | if (!player.isAdmin) { 69 | player.getConnection().sendServerMessage("只有管理才可以生成该单位!"); 70 | } 71 | } 72 | try { 73 | player.getRoom().broadcast(Packet.gameSummon(player.getRoom(), unit, event.getTargetX(), event.getTargetY(), player.playerIndex)); 74 | } catch (IOException ignored) {} 75 | player.putTempData("isSpawnTriggered", false); 76 | } 77 | } 78 | 79 | public class StopCallback implements ChatCommandListener { 80 | @Override 81 | public boolean onSend(RoomConnection con, String[] args) { 82 | con.currectRoom.stopGame(true); 83 | return false; 84 | } 85 | } 86 | 87 | @Override 88 | public void onLoad() { 89 | getLogger().info("TestPlugin is loading..."); 90 | testConfig = new TestPluginConfig(); 91 | getPluginManager().registerEventListener(this, this); 92 | try { 93 | File pluginFile = getConfigFile("config"); 94 | if (pluginFile.length() == 0) { 95 | saveConfig(pluginFile, testConfig); 96 | } 97 | testConfig = getConfig(pluginFile, TestPluginConfig.class); 98 | } catch (IOException e) { 99 | getLogger().warn("Config cannot be loaded."); 100 | } 101 | Rukkit.getCommandManager().registerCommand(new ChatCommand("summon", "Summon a unit.", 1, new SummonCallback(), this)); 102 | Rukkit.getCommandManager().registerCommand(new ChatCommand("gamestop", "Stop a game immidately and return to the battleroom", 0, new StopCallback(), this)); 103 | Rukkit.getCommandManager().registerCommand(new ChatCommand("testsync", "Sync", 0, new TestSyncCallback(), this)); 104 | } 105 | 106 | @Override 107 | public void onEnable() { 108 | 109 | } 110 | 111 | @Override 112 | public void onDisable() { 113 | 114 | } 115 | 116 | @Override 117 | public void onStart() { 118 | getLogger().info("Plugin is starting.."); 119 | } 120 | 121 | @Override 122 | public void onDone() { 123 | 124 | } 125 | 126 | @Override 127 | public void loadConfig() { 128 | config = new PluginConfig(); 129 | config.name = "TestPlugin2.0"; 130 | config.author = "rukkit"; 131 | config.version = "1.0.0"; 132 | config.id = "test-plugin"; 133 | config.pluginClass = "cn.rukkit.plugin.internal.NewTestPlugin"; 134 | config.apiVersion = Rukkit.PLUGIN_API_VERSION; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/plugin/internal/TestPluginConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.plugin.internal; 11 | 12 | public class TestPluginConfig { 13 | public long cd = 5 * 1000; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/service/Service.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.service; 11 | 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | public abstract class Service 16 | { 17 | /** 18 | * Service internal logger. 19 | */ 20 | public Logger log = LoggerFactory.getLogger(getClass()); 21 | 22 | /** 23 | * On service start. 24 | */ 25 | public abstract void onEnable(); 26 | public abstract void onDisable(); 27 | public abstract void onRegister(); 28 | } -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/service/ServiceManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.service; 11 | 12 | import cn.rukkit.plugin.Plugin; 13 | 14 | import java.util.HashMap; 15 | import java.util.List; 16 | 17 | public class ServiceManager 18 | { 19 | public HashMap services; 20 | public ServiceManager() { 21 | 22 | } 23 | 24 | public void registerService (Plugin fromPlugin, Service service) { 25 | // now have a register! 26 | } 27 | 28 | public void enableService(Service service) { 29 | 30 | } 31 | 32 | public void enableService(String serviceName) {} 33 | } -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/service/TerminalService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.service; 11 | 12 | public class TerminalService extends Service{ 13 | 14 | @Override 15 | public void onEnable() { 16 | 17 | } 18 | 19 | @Override 20 | public void onDisable() { 21 | 22 | } 23 | 24 | @Override 25 | public void onRegister() { 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/service/ThreadManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.service; 11 | import java.util.concurrent.*; 12 | 13 | public class ThreadManager 14 | { 15 | ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(8); 16 | 17 | /** 18 | * init a thread manager. 19 | * @param poolCount threadPool thread count. 20 | * @return ScheduledFuture 21 | */ 22 | public ThreadManager(int poolCount){ 23 | executorService = new ScheduledThreadPoolExecutor(poolCount); 24 | } 25 | 26 | /** 27 | * Schedule a task. 28 | * @param runnable Runnable task. 29 | * @param initialDelay after ~ms task will be scheduled. 30 | * @return ScheduledFuture 31 | */ 32 | public ScheduledFuture schedule(Runnable runnable, int initialDelay) { 33 | return executorService.schedule(runnable, initialDelay, TimeUnit.MILLISECONDS); 34 | } 35 | 36 | /** 37 | * Schedule a task. 38 | * @param runnable Runnable task. 39 | * @param initialDelay after ~ms task will be scheduled. 40 | * @param delay every ~ms task will be scheduled. 41 | * @return ScheduledFuture 42 | */ 43 | public ScheduledFuture schedule(Runnable runnable, int initialDelay, int delay) { 44 | ScheduledFuture t = executorService.scheduleWithFixedDelay(runnable, initialDelay, delay,TimeUnit.MILLISECONDS); 45 | return t; 46 | } 47 | 48 | /** 49 | * Schedule a task without schedule. 50 | * @param runnable Runnable task. 51 | * @return Future 52 | */ 53 | public Future submit(Runnable runnable) { 54 | return executorService.submit(runnable); 55 | } 56 | 57 | public void shutdown() { 58 | executorService.shutdown(); 59 | } 60 | 61 | public void shutdownTask(ScheduledFuture future) { 62 | future.cancel(true); 63 | } 64 | 65 | public long getTaskCount () { 66 | return executorService.getTaskCount(); 67 | } 68 | 69 | public int getActiveThreadCount() { 70 | return executorService.getActiveCount(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/util/GameUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.util; 11 | 12 | 13 | public class GameUtils 14 | { 15 | public static int getMoneyFormat(int n2) 16 | { 17 | if (n2 == 4000) 18 | { 19 | return 0; 20 | } 21 | if (n2 == 0) 22 | { 23 | return 1; 24 | } 25 | if (n2 == 1000) 26 | { 27 | return 2; 28 | } 29 | if (n2 == 2000) 30 | { 31 | return 3; 32 | } 33 | if (n2 == 5000) 34 | { 35 | return 4; 36 | } 37 | if (n2 == 10000) 38 | { 39 | return 5; 40 | } 41 | if (n2 == 50000) 42 | { 43 | return 6; 44 | } 45 | if (n2 == 100000) 46 | { 47 | return 7; 48 | } 49 | if (n2 != 200000) return 8; 50 | return 8; 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/util/LangUtil.java: -------------------------------------------------------------------------------- 1 | package cn.rukkit.util; 2 | import java.nio.charset.StandardCharsets; 3 | import java.text.MessageFormat; 4 | import java.util.Locale; 5 | import java.util.ResourceBundle; 6 | 7 | public class LangUtil { 8 | public static Locale lc = Locale.getDefault(); 9 | private static ResourceBundle bundle; 10 | 11 | public static void setLocale(Locale locale) { 12 | lc = locale; 13 | } 14 | 15 | public static String getString(String text) { 16 | if (bundle == null || bundle.getLocale() != lc) { 17 | ResourceBundle bd = ResourceBundle.getBundle("i18n/messages", lc); 18 | bundle = bd; 19 | } 20 | return new String(bundle.getString(text).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); 21 | } 22 | 23 | public static String getFormatString(String text, Object ... format) { 24 | return MessageFormat.format(getString(text), format); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/util/MathUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.util; 11 | 12 | public class MathUtil 13 | { 14 | @SuppressWarnings(value = {"all"}) 15 | public static final /*strictfp*/ int abs(int n2) { 16 | return n2 < 0 ? -n2 : n2; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/util/VerifyUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.util; 11 | 12 | public class VerifyUtil 13 | { 14 | } -------------------------------------------------------------------------------- /src/main/java/cn/rukkit/util/Vote.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 RukkitDev Team and contributors. 3 | * 4 | * This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | * 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | * 7 | * https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | */ 9 | 10 | package cn.rukkit.util; 11 | 12 | import cn.rukkit.Rukkit; 13 | import cn.rukkit.network.NetworkRoom; 14 | import cn.rukkit.network.RoomConnectionManager; 15 | 16 | import java.text.MessageFormat; 17 | import java.util.Arrays; 18 | import java.util.concurrent.ScheduledFuture; 19 | 20 | public class Vote{ 21 | // 投票id 22 | public String voteId = "null"; 23 | // 房间实例 24 | NetworkRoom room; 25 | private int agree = 0; 26 | private int disagree = 0; 27 | private int timeRemain = 15; 28 | private ScheduledFuture voteFuture; 29 | public String voteDesc = ""; 30 | 31 | boolean[] voteState; 32 | public boolean isVoting = false; 33 | 34 | public boolean disabledVote = false; 35 | 36 | public boolean submitVoting(final Runnable runnable, String id, String reason, int timeRem) { 37 | if (isVoting) { 38 | return false; 39 | } 40 | RoomConnectionManager con = room.connectionManager; 41 | con.broadcastServerMessage(reason); 42 | timeRemain = timeRem; 43 | voteId = id; 44 | voteDesc = reason; 45 | voteFuture = Rukkit.getThreadManager().schedule( 46 | new Runnable() { 47 | @Override 48 | public void run() { 49 | // No player exists.Stop vote. 50 | if (room.connectionManager.size() <= 0) { 51 | stopVote(); 52 | } 53 | if (timeRemain == 0) { 54 | if (agree >= disagree) { 55 | con.broadcastServerMessage( 56 | MessageFormat.format(LangUtil.getString("nostop.vote.success"), agree, disagree)); 57 | runnable.run(); 58 | } else { 59 | con.broadcastServerMessage( 60 | MessageFormat.format(LangUtil.getString("nostop.vote.failure"), agree, disagree)); 61 | } 62 | stopVote(); 63 | } 64 | if (timeRemain % 10 == 0) { 65 | con.broadcastServerMessage(MessageFormat.format(LangUtil.getString("nostop.vote.timeRemain"), timeRemain)); 66 | } 67 | timeRemain --; 68 | } 69 | }, 1000, 1000); 70 | isVoting = true; 71 | return true; 72 | } 73 | 74 | public Vote(NetworkRoom room) { 75 | this.room = room; 76 | voteState = new boolean[room.playerManager.getMaxPlayer()]; 77 | } 78 | 79 | public boolean agree(int index) { 80 | if (isVoting && !voteState[index]) { 81 | agree++; 82 | voteState[index] = true; 83 | return true; 84 | } 85 | return false; 86 | } 87 | 88 | public boolean disagree(int index) { 89 | if (isVoting && !voteState[index]) { 90 | disagree++; 91 | voteState[index] = true; 92 | return true; 93 | } 94 | return false; 95 | } 96 | 97 | public void stopVote() { 98 | isVoting = false; 99 | agree = disagree = 0; 100 | disabledVote = false; 101 | Arrays.fill(voteState, false); 102 | if (voteFuture != null) Rukkit.getThreadManager().shutdownTask(voteFuture); 103 | } 104 | } -------------------------------------------------------------------------------- /src/main/resources/defaultSave: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RukkitDev/Rukkit/4764085cda35428fe920ecbd0fbc2fd70c6f72b2/src/main/resources/defaultSave -------------------------------------------------------------------------------- /src/main/resources/i18n/messages.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020-2022 RukkitDev Team and contributors. 3 | # 4 | # This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | # 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | # 7 | # https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | # 9 | 10 | # Chat command plugin. 11 | chat.help=显示帮助 12 | chat.state=显示服务器状态 13 | chat.version=显示 Rukkit 版本 14 | chat.t=发送队伍消息 15 | chat.maps=获取官方地图列表 16 | chat.map=使用地图序号换图 17 | chat.cmaps=获取服务器上自定义地图列表 18 | chat.cmap=使用地图序号更换自定义地图 19 | chat.kick=(管理)踢出一个玩家 20 | chat.team=(管理)更换玩家队伍 21 | chat.self_team=更换自己的队伍 22 | chat.move=(管理)更换玩家位置 23 | chat.self_move=更换自己的位置 24 | chat.qc=静默执行命令 25 | chat.fog=设置雾类型 26 | chat.nukes=设置核弹是否启用(true/false) 27 | chat.startingunits=设置初始单位 28 | chat.income=设置资金倍数(1x-100x). 29 | chat.share=关闭/开启共享控制.(on/off) 30 | chat.credits=设置起始资金. 31 | chat.start=启动一场游戏. 32 | chat.sync=同步游戏(admin only.) 33 | chat.i=提交问题到服务器. 34 | chat.chksum=(开发者)广播同步检查. 35 | chat.maping=Ping 一个地方. 36 | chat.list=显示玩家列表. 37 | chat.surrender=投降. 38 | chat.kicked=被管理踢出. 39 | chat.teamMsg=[队伍消息] 40 | chat.moveComplete=移动成功! 41 | chat.playerExist=失败:已经有一个玩家在那个位置! 42 | chat.playerEmpty=玩家不存在! 43 | chat.minStartPlayer=至少要 {0} 人才能开始游戏! 44 | chat.invalidCommand=指令不存在。输入 ".help" 查看指令帮助。 45 | chat.privDenied=权限不足,无法使用! 46 | chat.afk=对挂机管理进行夺权。 47 | chat.vote.afk=玩家 {0} 发起对房主的 afk 请求! 48 | 49 | # No stop plugin 50 | nostop.y=同意当前投票. 51 | nostop.n=反对当前投票. 52 | nostop.vote.submit=投票成功! 53 | nostop.vote.alreadySubmit=你已经投过票了! 54 | nostop.vote.noCurrentVote=没有正在进行的投票! 55 | nostop.vote.success={0} 人同意, {1} 人拒绝.投票成功! 56 | nostop.vote.failure={0} 人同意, {1} 人拒绝.投票失败! 57 | nostop.vote.timeRemain=时间剩余 {0} 秒! 58 | nostop.vote.voteExist=已经有一个投票在进行了! 59 | nostop.vote.joinMessage={0} 加入了游戏! 60 | nostop.vote.map=玩家 {0} 投票更换地图到 {1}.发送(-y或-n) 来 同意/反对该投票! 61 | nostop.vote.cmap=玩家 {0} 投票更换自定义地图到 {1}.发送(-y或-n) 来 同意/反对该投票! 62 | nostop.vote.sync=玩家 {0} 投票进行游戏同步.发送(-y或-n) 来 同意/反对该投票! 63 | nostop.vote.income=玩家 {0} 投票修改资金倍数到 {1}x.发送(-y或-n) 来 同意/反对该投票! 64 | nostop.vote.nukes=玩家 {0} 投票修改禁核为 {1}.发送(-y或-n) 来 同意/反对该投票! 65 | nostop.move=玩家 {0} 从 {1} 移动到了 {2} 位置上! 66 | 67 | # Server command. 68 | server.kickAll=踢出当前正在服务器中的玩家。 69 | server.shutdown=关闭当前服务器。 70 | server.say=发布一条来自服务器的消息。 71 | 72 | # Rukkit base 73 | rukkit.playerRegister=你正在登陆 Rukkit 服务器! 74 | rukkit.playerJoin=玩家 {0} 加入了服务器! 75 | rukkit.playerLeft=玩家 {0} 离开了服务器({1})! 76 | rukkit.gameFull=服务器已满! 77 | rukkit.playerGotAdmin=你现在是服务器内的管理员! 78 | rukkit.gameStarted=游戏已开始! 79 | rukkit.playerReady=玩家 {0} 已准备! 80 | rukkit.playerReconnect=玩家 {0} 已重新连接! 81 | rukkit.playerSharingControlDueDisconnected=断开连接时,自动分享控制. 82 | rukkit.room=您现在在 {0} 号房间! 83 | 84 | # Plugin Load 85 | rukkit.plugin.invalid=Jar文件 {0}.jar 不是有效的 Rukkit 插件!请检查 plugin.yml! -------------------------------------------------------------------------------- /src/main/resources/i18n/messages_en_US.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020-2022 RukkitDev Team and contributors. 3 | # 4 | # This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | # 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | # 7 | # https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | # 9 | 10 | chat.help=Show help. 11 | chat.state=Show Server State. 12 | chat.version=Show Rukkit Version. 13 | chat.t=Send a team message. 14 | chat.maps=Get official maps list. 15 | chat.map=Change map to map with id in map list. 16 | chat.cmaps=Get custom maps list. 17 | chat.cmap=Change custom map to map with id in map list. 18 | chat.kick=Kick a player. 19 | chat.team=Change a player's ally. 20 | chat.self_team=Change yourself ally. 21 | chat.move=Move a player. 22 | chat.self_move=Move yourself. 23 | chat.qc=Execute a command silently. 24 | chat.fog=Set fog type in game. 25 | chat.nukes=Set nukes enabled in game. 26 | chat.startingunits=Set starting units in game. 27 | chat.income=Set income in game(1x-100x). 28 | chat.share=Set your share state in game.(on/off) 29 | chat.credits=Set default credits in game. 30 | chat.start=Start a game. 31 | chat.sync=Sync a game(admin only.) 32 | chat.i=Submit a info message to server. 33 | chat.chksum=Send a Chksum to client. 34 | chat.maping=Ping map. 35 | chat.list=Show player list. 36 | chat.surrender=surrender. 37 | chat.kicked=Kicked by Admin. 38 | chat.teamMsg=[TEAM] 39 | chat.moveComplete=Move complete! 40 | chat.playerExist=Fail: already have a player in that slot! 41 | chat.playerEmpty=Player isn't exists! 42 | chat.minStartPlayer=Min start player is {0}! 43 | chat.invalidCommand=Command not exist.Try '.help' to list all commands. 44 | chat.privDenied=You dont have the permission to execute it! 45 | chat.afk=Afk a admin. 46 | nostop.y=Argee current voting. 47 | nostop.n=Disargee current voting. 48 | nostop.vote.submit=Voted! 49 | nostop.vote.alreadySubmit=You had already Voted! 50 | nostop.vote.noCurrentVote=No Vote is running! 51 | nostop.vote.success=Argee: {0}, Disargee {1}.Vote success! 52 | nostop.vote.failure=Argee: {0}, Disargee {1}.Vote failed! 53 | nostop.vote.timeRemain=Time remaining {0} s! 54 | nostop.vote.voteExist=Already have a vote! 55 | nostop.vote.joinMessage={0} 56 | nostop.vote.map=Player {0} wants to change map to {1}.Send(-y/-n) to argee/disargee! 57 | nostop.vote.cmap=Player {0} wants to change custom map to {1}.Send(-y/-n) to argee/disargee! 58 | nostop.vote.sync=Player {0} wants to resync.Send(-y/-n) to argee/disargee! 59 | nostop.vote.income=Player {0} wants to change income rate to {1}x.Send(-y/-n) to argee/disargee! 60 | nostop.vote.nukes=Player {0} wants to change nukes to {1}.Send(-y/-n) to argee/disargee! 61 | nostop.move=Player {0} moved his position from {1} to {2}! 62 | chat.vote.afk=Player {0} requested to afk the admin! 63 | 64 | # Server command. 65 | server.kickAll=Kick current players in server. 66 | server.shutdown=Shutdown server. 67 | server.say=Say a message from server. 68 | 69 | # Rukkit base 70 | rukkit.playerRegister=You are logging to Rukkit. 71 | rukkit.room=You are in the Room #{0}! 72 | rukkit.playerJoin=Player {0} joined the server! 73 | rukkit.playerLeft=Player {0} left the server({1})! 74 | rukkit.gameFull=Game is full! 75 | rukkit.playerGotAdmin=You are the ADMIN of this server! 76 | rukkit.gameStarted=Game is started! 77 | rukkit.playerReady=Player {0} is ready. 78 | rukkit.playerReconnect=Player {0} reconnected! 79 | rukkit.playerSharingControlDueDisconnected=Sharing control due to disconnected. 80 | rukkit.plugin.invalid=Jar {0},jar is not a vaild Rukkit plugin!Please check plugin.yml! -------------------------------------------------------------------------------- /src/main/resources/i18n/messages_ru.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020-2022 RukkitDev Team and contributors. 3 | # 4 | # This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | # 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | # 7 | # https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | # 9 | 10 | # Chat command plugin. 11 | chat.help=Показать 'help'. 12 | chat.state=Показать состояние сервера. 13 | chat.version=Показать версию Rukkit. 14 | chat.t=Отправить командное сообщение. 15 | chat.maps=Получить список официальных карт. 16 | chat.map=Укажите номер официальной карты, чтобы переключиться на неё. 17 | chat.cmaps=Получить список кастомных карт. 18 | chat.cmap=Укажите номер кастомной карты, чтобы переключиться на неё. 19 | chat.kick=(Админ) Выгнать игрока. 20 | chat.team=(Админ) Поменять команду игрока. 21 | chat.self_team=Поменять свою команду. 22 | chat.move=(Админ) Поменять позицию спавна игрока. 23 | chat.self_move=Поменять свою позицию спавна. 24 | chat.qc=Тихо исполнить команду. 25 | chat.fog=Указать тип тумана войны в игре. 26 | chat.nukes=Указать, включено ли ядерное оружие (true/false). 27 | chat.startingunits=Указать стартовых юнитов. 28 | chat.income=Указать множитель дохода (1x-100x). 29 | chat.share=Указать, включен ли общий доступ (on/off). 30 | chat.credits=Указать начальное количество кредитов. 31 | chat.start=Начать игру. 32 | chat.sync=Синхронизировать игру (только для админов). 33 | chat.i=Отправить информацию на сервер. 34 | chat.chksum=Отправить Chksum клиенту. 35 | chat.maping=Поставить метку на место. 36 | chat.list=Показать список игроков. 37 | chat.surrender=Сдаться. 38 | chat.kicked=Вы были выгнаны администратором. 39 | chat.teamMsg=[Командный] 40 | chat.moveComplete=Вы успешно поменяли место спавна\! 41 | chat.playerExist=Ошибка\: данное место спавна уже занято другим игроком\! 42 | chat.playerEmpty=Игрок не найден\! 43 | chat.minStartPlayer=Для начала игры нужно {0} игроков\! 44 | chat.invalidCommand=Данная команда не существует. Напишите ".help" чтобы увидеть список команд. 45 | chat.privDenied=Недостаточно привилегий для исполнения команды\! 46 | # No stop plugin 47 | nostop.y=Согласиться с текущем голосованием. 48 | nostop.n=Отказаться от текущего голосования. 49 | nostop.vote.submit=Вы успешно проголосовали\! 50 | nostop.vote.alreadySubmit=Вы уже проголосовали ранее\! 51 | nostop.vote.noCurrentVote=Сейчас не идет голосование\! 52 | nostop.vote.success={0} игроков согласились, {1} выступили против. Голосование успешно завершено\! 53 | nostop.vote.failure={0} игроков согласились, {1} выступили против. Голосование провалилось\! 54 | nostop.vote.timeRemain={0} секунд осталось\! 55 | nostop.vote.voteExist=Сейчас уже идет голосование\! 56 | nostop.vote.joinMessage={0} 57 | nostop.vote.map=Игрок {0} начал голосование за смену карты на\: {1}. Отправьте (-y или -n) чтобы согласиться или отказаться\! 58 | nostop.vote.cmap=Игрок {0} начал голосование за смену карты на кастомную\: {1}. Отправьте (-y или -n) чтобы согласиться или отказаться\! 59 | nostop.vote.sync=Игрок {0} начал голосование за синхронизацию сервера. Отправьте (-y или -n) чтобы согласиться или отказаться\! 60 | nostop.vote.income=Игрок {0} начал голосование за смену множителя дохода на {1}x. Отправьте (-y или -n) чтобы согласиться или отказаться\! 61 | nostop.vote.nukes=Игрок {0} начал голосование за ядерное оружие\: {1}. Отправьте (-y или -n) чтобы согласиться или отказаться\! 62 | nostop.move=Игрок {0} поменял свой спавн с {1} на {2}\! 63 | 64 | # Server command. 65 | server.kickAll=Выгнать всех с сервера. 66 | server.shutdown=Выключить сервер. 67 | server.say=Отправить сообщение от лица сервера. 68 | 69 | # Rukkit base 70 | rukkit.playerRegister=Вы подключены к Rukkit серверу\! 71 | rukkit.playerJoin=Игрок {0} присоединился к комнате\! 72 | rukkit.playerLeft=Игрок {0} вышел с комнаты\! 73 | rukkit.gameFull=Сервер переполнен\! 74 | rukkit.playerGotAdmin=Вы теперь администратор комнаты\! 75 | rukkit.gameStarted=Игра началась\! 76 | rukkit.playerReady=Игрок {0} готов. 77 | 78 | # Plugin Load 79 | rukkit.plugin.invalid=Jar файл {0}.jar не поддерживается Rukkit! Пожалуйста, проверьте plugin.yml! 80 | rukkit.playerReconnect=Player {0} reconnected! 81 | rukkit.playerSharingControlDueDisconnected=Sharing control due to disconnected. 82 | rukkit.room=You are in the Room #{0}! -------------------------------------------------------------------------------- /src/main/resources/i18n/messages_zh_CN.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020-2022 RukkitDev Team and contributors. 3 | # 4 | # This project uses GNU Affero General Public License v3.0.You can find this license in the following link. 5 | # 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看: 6 | # 7 | # https://github.com/RukkitDev/Rukkit/blob/master/LICENSE 8 | # 9 | 10 | # Chat command plugin. 11 | chat.help=显示帮助 12 | chat.state=显示服务器状态 13 | chat.version=显示 Rukkit 版本 14 | chat.t=发送队伍消息 15 | chat.maps=获取官方地图列表 16 | chat.map=使用地图序号换图 17 | chat.cmaps=获取服务器上自定义地图列表 18 | chat.cmap=使用地图序号更换自定义地图 19 | chat.kick=(管理)踢出一个玩家 20 | chat.team=(管理)更换玩家队伍 21 | chat.self_team=更换自己的队伍 22 | chat.move=(管理)更换玩家位置 23 | chat.self_move=更换自己的位置 24 | chat.qc=静默执行命令 25 | chat.fog=设置雾类型 26 | chat.nukes=设置核弹是否启用(true/false) 27 | chat.startingunits=设置初始单位 28 | chat.income=设置资金倍数(1x-100x). 29 | chat.share=关闭/开启共享控制.(on/off) 30 | chat.credits=设置起始资金. 31 | chat.start=启动一场游戏. 32 | chat.sync=同步游戏(admin only.) 33 | chat.i=提交问题到服务器. 34 | chat.chksum=(开发者)广播同步检查. 35 | chat.maping=Ping 一个地方. 36 | chat.list=显示玩家列表. 37 | chat.surrender=投降. 38 | chat.kicked=被管理踢出. 39 | chat.teamMsg=[队伍消息] 40 | chat.moveComplete=移动成功! 41 | chat.playerExist=失败:已经有一个玩家在那个位置! 42 | chat.playerEmpty=玩家不存在! 43 | chat.minStartPlayer=至少要 {0} 人才能开始游戏! 44 | chat.invalidCommand=指令不存在。输入 ".help" 查看指令帮助。 45 | chat.privDenied=权限不足,无法使用! 46 | chat.afk=对挂机管理进行夺权。 47 | chat.vote.afk=玩家 {0} 发起对房主的 afk 请求! 48 | 49 | # No stop plugin 50 | nostop.y=同意当前投票. 51 | nostop.n=反对当前投票. 52 | nostop.vote.submit=投票成功! 53 | nostop.vote.alreadySubmit=你已经投过票了! 54 | nostop.vote.noCurrentVote=没有正在进行的投票! 55 | nostop.vote.success={0} 人同意, {1} 人拒绝.投票成功! 56 | nostop.vote.failure={0} 人同意, {1} 人拒绝.投票失败! 57 | nostop.vote.timeRemain=时间剩余 {0} 秒! 58 | nostop.vote.voteExist=已经有一个投票在进行了! 59 | nostop.vote.joinMessage={0} 加入了游戏! 60 | nostop.vote.map=玩家 {0} 投票更换地图到 {1}.发送(-y或-n) 来 同意/反对该投票! 61 | nostop.vote.cmap=玩家 {0} 投票更换自定义地图到 {1}.发送(-y或-n) 来 同意/反对该投票! 62 | nostop.vote.sync=玩家 {0} 投票进行游戏同步.发送(-y或-n) 来 同意/反对该投票! 63 | nostop.vote.income=玩家 {0} 投票修改资金倍数到 {1}x.发送(-y或-n) 来 同意/反对该投票! 64 | nostop.vote.nukes=玩家 {0} 投票修改禁核为 {1}.发送(-y或-n) 来 同意/反对该投票! 65 | nostop.move=玩家 {0} 从 {1} 移动到了 {2} 位置上! 66 | 67 | # Server command. 68 | server.kickAll=踢出当前正在服务器中的玩家。 69 | server.shutdown=关闭当前服务器。 70 | server.say=发布一条来自服务器的消息。 71 | 72 | # Rukkit base 73 | rukkit.playerRegister=你正在登陆 Rukkit 服务器! 74 | rukkit.playerJoin=玩家 {0} 加入了服务器! 75 | rukkit.playerLeft=玩家 {0} 离开了服务器({1})! 76 | rukkit.gameFull=服务器已满! 77 | rukkit.playerGotAdmin=你现在是服务器内的管理员! 78 | rukkit.gameStarted=游戏已开始! 79 | rukkit.playerReady=玩家 {0} 已准备! 80 | rukkit.playerReconnect=玩家 {0} 已重新连接! 81 | rukkit.playerSharingControlDueDisconnected=断开连接时,自动分享控制. 82 | rukkit.room=您现在在 {0} 号房间! 83 | 84 | # Plugin Load 85 | rukkit.plugin.invalid=Jar文件 {0}.jar 不是有效的 Rukkit 插件!请检查 plugin.yml! -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | lastrun.log 13 | 14 | [%d{yyyy-MM-dd HH:mm:ss} %level] [%logger{50}]: %msg%n 15 | 16 | 17 | 18 | 19 | 20 | %yellow([%d{yyyy-MM-dd HH:mm:ss} %level]) %-5highlight([%logger{0}]): %msg%n 21 | 22 | 23 | 24 | 25 | 26 | %yellow([%d{yyyy-MM-dd HH:mm:ss} %level]) %-5highlight([%logger{0}]): %msg%n 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/main/resources/mod_default.1.14.json: -------------------------------------------------------------------------------- 1 | [{"modName":"default","unitId":860970606,"unitName":"aaBeamGunship"},{"modName":"default","unitId":219143883,"unitName":"aaBeamGunship_afterburn"},{"modName":"default","unitId":1677180627,"unitName":"c_amphibiousJet"},{"modName":"default","unitId":-370185172,"unitName":"c_amphibiousJet_transition"},{"modName":"default","unitId":-1072729755,"unitName":"c_amphibiousJet_underwater"},{"modName":"default","unitId":-1389433744,"unitName":"bomber"},{"modName":"default","unitId":-1936941610,"unitName":"bugGeneratorN"},{"modName":"default","unitId":-1926767803,"unitName":"bugGeneratorNT2"},{"modName":"default","unitId":1667018571,"unitName":"bugMeleeT31"},{"modName":"default","unitId":1130542821,"unitName":"bugBee"},{"modName":"default","unitId":-2140934933,"unitName":"bugExtractor"},{"modName":"default","unitId":-982209524,"unitName":"bugExtractorT2"},{"modName":"default","unitId":-635695326,"unitName":"bugFly"},{"modName":"default","unitId":-1773752922,"unitName":"bugGenerator"},{"modName":"default","unitId":489032784,"unitName":"bugGeneratorT2"},{"modName":"default","unitId":-729991278,"unitName":"bugMelee"},{"modName":"default","unitId":-2021833635,"unitName":"bugMeleeLarge"},{"modName":"default","unitId":-1874773521,"unitName":"bugMeleeSmall"},{"modName":"default","unitId":1800067153,"unitName":"bugNest"},{"modName":"default","unitId":-1897691533,"unitName":"bugRanged"},{"modName":"default","unitId":65055111,"unitName":"bugSpore"},{"modName":"default","unitId":-1403199191,"unitName":"bugTurret"},{"modName":"default","unitId":1361654426,"unitName":"bugPickup"},{"modName":"default","unitId":-1211095214,"unitName":"bugWasp"},{"modName":"default","unitId":-1913499349,"unitName":"bugRangedT2"},{"modName":"default","unitId":2086815533,"unitName":"combatEngineer"},{"modName":"default","unitId":-1557495871,"unitName":"experiementalCarrier"},{"modName":"default","unitId":846063198,"unitName":"experimentalDropship"},{"modName":"default","unitId":1147938148,"unitName":"experimentalGunship"},{"modName":"default","unitId":247396735,"unitName":"experimentalGunshipLanded"},{"modName":"default","unitId":1153097492,"unitName":"experimentalSpider"},{"modName":"default","unitId":-1425308496,"unitName":"c_experimentalTank"},{"modName":"default","unitId":1131863716,"unitName":"extractorT1"},{"modName":"default","unitId":1968739682,"unitName":"extractorT2"},{"modName":"default","unitId":-1752577323,"unitName":"extractorT3"},{"modName":"default","unitId":-946861607,"unitName":"extractorT3_overclocked"},{"modName":"default","unitId":586038299,"unitName":"extractorT3_reinforced"},{"modName":"default","unitId":2146490194,"unitName":"fabricatorT1"},{"modName":"default","unitId":-434268756,"unitName":"fabricatorT2"},{"modName":"default","unitId":-1633034217,"unitName":"fabricatorT3"},{"modName":"default","unitId":1311846917,"unitName":"fireBee"},{"modName":"default","unitId":1505640793,"unitName":"heavyBattleship"},{"modName":"default","unitId":-1765179497,"unitName":"heavyInterceptor"},{"modName":"default","unitId":-1563896665,"unitName":"heavyMissileShip"},{"modName":"default","unitId":234576834,"unitName":"heavySub"},{"modName":"default","unitId":1849420775,"unitName":"c_helicopter"},{"modName":"default","unitId":-1749180314,"unitName":"c_interceptor"},{"modName":"default","unitId":-2079658632,"unitName":"laboratory"},{"modName":"default","unitId":-200788090,"unitName":"c_laserTank"},{"modName":"default","unitId":-227203220,"unitName":"lightGunship"},{"modName":"default","unitId":-1273802215,"unitName":"lightSub"},{"modName":"default","unitId":1350092776,"unitName":"c_mammothTank"},{"modName":"default","unitId":-1070292262,"unitName":"mechEngineer"},{"modName":"default","unitId":1695051981,"unitName":"mechFactory"},{"modName":"default","unitId":-1828960398,"unitName":"mechFactoryT2"},{"modName":"default","unitId":-521717810,"unitName":"mechArtillery"},{"modName":"default","unitId":1391543916,"unitName":"mechBunker"},{"modName":"default","unitId":1776045873,"unitName":"mechBunkerDeployed"},{"modName":"default","unitId":1379194430,"unitName":"mechFlame"},{"modName":"default","unitId":1657090150,"unitName":"mechFlyingLanded"},{"modName":"default","unitId":-1620153849,"unitName":"mechFlyingTakeoff"},{"modName":"default","unitId":-788457542,"unitName":"mechHeavyMissile"},{"modName":"default","unitId":-10547272,"unitName":"mechLaser"},{"modName":"default","unitId":-740223522,"unitName":"mechLightning"},{"modName":"default","unitId":932768776,"unitName":"mechMinigun"},{"modName":"default","unitId":1094172666,"unitName":"mechGun"},{"modName":"default","unitId":861951899,"unitName":"mechMissile"},{"modName":"default","unitId":761870113,"unitName":"flare_10s"},{"modName":"default","unitId":-1306704433,"unitName":"missileAirship"},{"modName":"default","unitId":-1895347353,"unitName":"missileTank"},{"modName":"default","unitId":1930152808,"unitName":"missing"},{"modName":"default","unitId":735847390,"unitName":"modularSpider_antiair"},{"modName":"default","unitId":-328463227,"unitName":"modularSpider_antiairFlak"},{"modName":"default","unitId":2076752865,"unitName":"modularSpider_antiairT2"},{"modName":"default","unitId":-1892607102,"unitName":"modularSpider_antinuke"},{"modName":"default","unitId":-1861308737,"unitName":"modularSpider_artillery"},{"modName":"default","unitId":-949937458,"unitName":"modularSpider_emptySlot"},{"modName":"default","unitId":1100550896,"unitName":"modularSpider_fabricator"},{"modName":"default","unitId":810261095,"unitName":"modularSpider_fabricatorT2"},{"modName":"default","unitId":307661720,"unitName":"modularSpider_gunturret"},{"modName":"default","unitId":-1121363802,"unitName":"modularSpider_gunturretT2"},{"modName":"default","unitId":-1698779767,"unitName":"modularSpider_laserdefense"},{"modName":"default","unitId":2051060413,"unitName":"modularSpider_lightning"},{"modName":"default","unitId":-1643516835,"unitName":"modularSpider"},{"modName":"default","unitId":-821428392,"unitName":"modularSpider_nonEmpty"},{"modName":"default","unitId":-1725933258,"unitName":"modularSpider_shieldGen"},{"modName":"default","unitId":-1271861377,"unitName":"modularSpider_smallgunturret"},{"modName":"default","unitId":1926906129,"unitName":"modularSpider_smallgunturretT2"},{"modName":"default","unitId":1670375609,"unitName":"nautilusSubmarine"},{"modName":"default","unitId":-801018660,"unitName":"nautilusSubmarineLand"},{"modName":"default","unitId":1805809924,"unitName":"nautilusSubmarineSurface"},{"modName":"default","unitId":238020095,"unitName":"robotCrab"},{"modName":"default","unitId":160216420,"unitName":"robotCrabWater"},{"modName":"default","unitId":801935096,"unitName":"antiNukeLauncherC"},{"modName":"default","unitId":1708014547,"unitName":"nukeLauncherC"},{"modName":"default","unitId":-58920905,"unitName":"outpostT1"},{"modName":"default","unitId":-853848219,"unitName":"outpostT2"},{"modName":"default","unitId":1892311963,"unitName":"plasmaTank"},{"modName":"default","unitId":-1294863888,"unitName":"creditsCrates"},{"modName":"default","unitId":543398471,"unitName":"crystal_mid"},{"modName":"default","unitId":830829287,"unitName":"scout"},{"modName":"default","unitId":-1549255731,"unitName":"c_artillery"},{"modName":"default","unitId":122041343,"unitName":"heavyArtillery"},{"modName":"default","unitId":-447318732,"unitName":"c_tank"},{"modName":"default","unitId":-1236108737,"unitName":"c_antiAirTurret"},{"modName":"default","unitId":115552836,"unitName":"antiAirTurretFlak"},{"modName":"default","unitId":1546433438,"unitName":"c_antiAirTurretT2"},{"modName":"default","unitId":-130304920,"unitName":"c_antiAirTurretT3"},{"modName":"default","unitId":1445115114,"unitName":"c_turret_t1"},{"modName":"default","unitId":-640961280,"unitName":"c_turret_t1_artillery"},{"modName":"default","unitId":-676121868,"unitName":"c_turret_t1_lightning"},{"modName":"default","unitId":1036632046,"unitName":"c_turret_t2_artillery"},{"modName":"default","unitId":-2005064100,"unitName":"c_turret_t2_flame"},{"modName":"default","unitId":1111779944,"unitName":"c_turret_t2_gun"},{"modName":"default","unitId":1570262950,"unitName":"c_turret_t2_lightning"},{"modName":"default","unitId":-2046696142,"unitName":"c_turret_t3_gun"}] -------------------------------------------------------------------------------- /src/main/resources/mod_default.json: -------------------------------------------------------------------------------- 1 | [{"modName":"default","unitId":-733624759,"unitName":"aaBeamGunship"},{"modName":"default","unitId":737842261,"unitName":"aaBeamGunship_afterburn"},{"modName":"default","unitId":1677180627,"unitName":"c_amphibiousJet"},{"modName":"default","unitId":-370185172,"unitName":"c_amphibiousJet_transition"},{"modName":"default","unitId":-1072729755,"unitName":"c_amphibiousJet_underwater"},{"modName":"default","unitId":-1389433744,"unitName":"bomber"},{"modName":"default","unitId":-1936941610,"unitName":"bugGeneratorN"},{"modName":"default","unitId":-1926767803,"unitName":"bugGeneratorNT2"},{"modName":"default","unitId":1667018571,"unitName":"bugMeleeT31"},{"modName":"default","unitId":1130542821,"unitName":"bugBee"},{"modName":"default","unitId":-2140934933,"unitName":"bugExtractor"},{"modName":"default","unitId":-982209524,"unitName":"bugExtractorT2"},{"modName":"default","unitId":-635695326,"unitName":"bugFly"},{"modName":"default","unitId":-1773752922,"unitName":"bugGenerator"},{"modName":"default","unitId":489032784,"unitName":"bugGeneratorT2"},{"modName":"default","unitId":-729991278,"unitName":"bugMelee"},{"modName":"default","unitId":-2021833635,"unitName":"bugMeleeLarge"},{"modName":"default","unitId":-1874773521,"unitName":"bugMeleeSmall"},{"modName":"default","unitId":1800067153,"unitName":"bugNest"},{"modName":"default","unitId":-1897691533,"unitName":"bugRanged"},{"modName":"default","unitId":65055111,"unitName":"bugSpore"},{"modName":"default","unitId":-1403199191,"unitName":"bugTurret"},{"modName":"default","unitId":1361654426,"unitName":"bugPickup"},{"modName":"default","unitId":-1211095214,"unitName":"bugWasp"},{"modName":"default","unitId":-1913499349,"unitName":"bugRangedT2"},{"modName":"default","unitId":-1123204953,"unitName":"combatEngineer"},{"modName":"default","unitId":-1557495871,"unitName":"experiementalCarrier"},{"modName":"default","unitId":846063198,"unitName":"experimentalDropship"},{"modName":"default","unitId":-1968367076,"unitName":"experimentalGunship"},{"modName":"default","unitId":401966168,"unitName":"experimentalGunshipLanded"},{"modName":"default","unitId":1153097492,"unitName":"experimentalSpider"},{"modName":"default","unitId":-1425308496,"unitName":"c_experimentalTank"},{"modName":"default","unitId":1131863716,"unitName":"extractorT1"},{"modName":"default","unitId":1968739682,"unitName":"extractorT2"},{"modName":"default","unitId":-1752577323,"unitName":"extractorT3"},{"modName":"default","unitId":-946861607,"unitName":"extractorT3_overclocked"},{"modName":"default","unitId":586038299,"unitName":"extractorT3_reinforced"},{"modName":"default","unitId":2146490194,"unitName":"fabricatorT1"},{"modName":"default","unitId":1776171717,"unitName":"fabricatorT2"},{"modName":"default","unitId":1469569962,"unitName":"fabricatorT3"},{"modName":"default","unitId":1311846917,"unitName":"fireBee"},{"modName":"default","unitId":443917916,"unitName":"heavyAAShip"},{"modName":"default","unitId":1505640793,"unitName":"heavyBattleship"},{"modName":"default","unitId":-1928280983,"unitName":"heavyInterceptor"},{"modName":"default","unitId":-1563896665,"unitName":"heavyMissileShip"},{"modName":"default","unitId":234576834,"unitName":"heavySub"},{"modName":"default","unitId":1849420775,"unitName":"c_helicopter"},{"modName":"default","unitId":-1749180314,"unitName":"c_interceptor"},{"modName":"default","unitId":-2079658632,"unitName":"laboratory"},{"modName":"default","unitId":-200788090,"unitName":"c_laserTank"},{"modName":"default","unitId":-227203220,"unitName":"lightGunship"},{"modName":"default","unitId":-1273802215,"unitName":"lightSub"},{"modName":"default","unitId":1350092776,"unitName":"c_mammothTank"},{"modName":"default","unitId":-1070292262,"unitName":"mechEngineer"},{"modName":"default","unitId":1695051981,"unitName":"mechFactory"},{"modName":"default","unitId":-1828960398,"unitName":"mechFactoryT2"},{"modName":"default","unitId":-521717810,"unitName":"mechArtillery"},{"modName":"default","unitId":1391543916,"unitName":"mechBunker"},{"modName":"default","unitId":1776045873,"unitName":"mechBunkerDeployed"},{"modName":"default","unitId":1379194430,"unitName":"mechFlame"},{"modName":"default","unitId":1657090150,"unitName":"mechFlyingLanded"},{"modName":"default","unitId":-1620153849,"unitName":"mechFlyingTakeoff"},{"modName":"default","unitId":-1268695302,"unitName":"mechHeavyMissile"},{"modName":"default","unitId":-10547272,"unitName":"mechLaser"},{"modName":"default","unitId":2115705030,"unitName":"mechLightning"},{"modName":"default","unitId":-1395794900,"unitName":"mechMinigun"},{"modName":"default","unitId":1094172666,"unitName":"mechGun"},{"modName":"default","unitId":861951899,"unitName":"mechMissile"},{"modName":"default","unitId":761870113,"unitName":"flare_10s"},{"modName":"default","unitId":1008075054,"unitName":"missileAirship"},{"modName":"default","unitId":-1895347353,"unitName":"missileTank"},{"modName":"default","unitId":1930152808,"unitName":"missing"},{"modName":"default","unitId":1410502760,"unitName":"modularSpider_antiair"},{"modName":"default","unitId":-288580706,"unitName":"modularSpider_antiairFlak"},{"modName":"default","unitId":-922201648,"unitName":"modularSpider_antiairT2"},{"modName":"default","unitId":687822558,"unitName":"modularSpider_antinuke"},{"modName":"default","unitId":-461254065,"unitName":"modularSpider_artillery"},{"modName":"default","unitId":-1925566271,"unitName":"modularSpider_blink"},{"modName":"default","unitId":-1351425979,"unitName":"modularSpider_emptySlot"},{"modName":"default","unitId":-1408828649,"unitName":"modularSpider_fabricator"},{"modName":"default","unitId":1826943095,"unitName":"modularSpider_fabricatorT2"},{"modName":"default","unitId":1488870876,"unitName":"modularSpider_gunturret"},{"modName":"default","unitId":136824729,"unitName":"modularSpider_gunturretT2"},{"modName":"default","unitId":-920139132,"unitName":"modularSpider_laserdefense"},{"modName":"default","unitId":-1967904792,"unitName":"modularSpider_lightning"},{"modName":"default","unitId":1541402670,"unitName":"modularSpider"},{"modName":"default","unitId":-760724615,"unitName":"modularSpider_nonEmpty"},{"modName":"default","unitId":83380146,"unitName":"modularSpider_shieldGen"},{"modName":"default","unitId":2030526116,"unitName":"modularSpider_smallgunturret"},{"modName":"default","unitId":-1167205893,"unitName":"modularSpider_smallgunturretT2"},{"modName":"default","unitId":-654357281,"unitName":"modularSpider_speed"},{"modName":"default","unitId":513472578,"unitName":"modularSpider_speedIncomplete"},{"modName":"default","unitId":-1011609993,"unitName":"nautilusSubmarine"},{"modName":"default","unitId":1553465464,"unitName":"nautilusSubmarineLand"},{"modName":"default","unitId":-1516082992,"unitName":"nautilusSubmarineSurface"},{"modName":"default","unitId":654318602,"unitName":"robotCrab"},{"modName":"default","unitId":1890478545,"unitName":"robotCrabWater"},{"modName":"default","unitId":-188463418,"unitName":"antiNukeLauncherC"},{"modName":"default","unitId":-2102839311,"unitName":"nukeLauncherC"},{"modName":"default","unitId":1354630724,"unitName":"outpostT1"},{"modName":"default","unitId":-2002121366,"unitName":"outpostT2"},{"modName":"default","unitId":1892311963,"unitName":"plasmaTank"},{"modName":"default","unitId":-1294863888,"unitName":"creditsCrates"},{"modName":"default","unitId":543398471,"unitName":"crystal_mid"},{"modName":"default","unitId":-1689798431,"unitName":"scout"},{"modName":"default","unitId":-1067723888,"unitName":"spyDrone"},{"modName":"default","unitId":-1549255731,"unitName":"c_artillery"},{"modName":"default","unitId":122041343,"unitName":"heavyArtillery"},{"modName":"default","unitId":-447318732,"unitName":"c_tank"},{"modName":"default","unitId":-1236108737,"unitName":"c_antiAirTurret"},{"modName":"default","unitId":115552836,"unitName":"antiAirTurretFlak"},{"modName":"default","unitId":1546433438,"unitName":"c_antiAirTurretT2"},{"modName":"default","unitId":-130304920,"unitName":"c_antiAirTurretT3"},{"modName":"default","unitId":1445115114,"unitName":"c_turret_t1"},{"modName":"default","unitId":-640961280,"unitName":"c_turret_t1_artillery"},{"modName":"default","unitId":-676121868,"unitName":"c_turret_t1_lightning"},{"modName":"default","unitId":1036632046,"unitName":"c_turret_t2_artillery"},{"modName":"default","unitId":-2005064100,"unitName":"c_turret_t2_flame"},{"modName":"default","unitId":1111779944,"unitName":"c_turret_t2_gun"},{"modName":"default","unitId":1570262950,"unitName":"c_turret_t2_lightning"},{"modName":"default","unitId":-2046696142,"unitName":"c_turret_t3_gun"}] -------------------------------------------------------------------------------- /start.bat: -------------------------------------------------------------------------------- 1 | java -Dfile.encoding=UTF-8 -Djava.library.path=. -cp "Rukkit-{version}.jar;libs/*" cn.rukkit.RukkitLauncher -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | java -Dfile.encoding=UTF-8 -Djava.library.path=. -cp Rukkit-{version}.jar:libs/* cn.rukkit.RukkitLauncher 2 | --------------------------------------------------------------------------------