diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a3e665d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,149 @@
+# Created by .ignore support plugin (hsz.mobi)
+### Eclipse template
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+.recommenders
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# PyDev specific (Python IDE for Eclipse)
+*.pydevproject
+
+# CDT-specific (C/C++ Development Tooling)
+.cproject
+
+# CDT- autotools
+.autotools
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific (PHP Development Tools)
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# Tern plugin
+.tern-project
+
+# TeXlipse plugin
+.texlipse
+
+# STS (Spring Tool Suite)
+.springBeans
+
+# Code Recommenders
+.recommenders/
+
+# Annotation Processing
+.apt_generated/
+.apt_generated_test/
+
+# Scala IDE specific (Scala & Java development for Eclipse)
+.cache-main
+.scala_dependencies
+.worksheet
+
+# Uncomment this line if you wish to ignore the project description file.
+# Typically, this file would be tracked if it contains build/dependency configurations:
+#.project
+
+
+
+### JetBrains template
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+
+
+
+### Project escape directories/files
+/.idea/
+/target/
+*.iml
+
+# Making private tests
+/src/test/java/com/antonio112009/steam4j/privatetest/
+Notes.txt
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..9be5ed9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Anton Rogalskiy and Steam4J contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..43964fe
--- /dev/null
+++ b/README.md
@@ -0,0 +1,158 @@
+add Java 15v
+add MIT Lisence
+add ..
+
+
+# Steam4J
+Steam4J is an open-source project that strives provides full wrapping of game server queries.
+
+## Navigation
+
+1. [Dependencies](##Dependencies)
+1. [Dependencies](##Features)
+1. [Dependencies](##Installation)
+
+
+##Dependencies
+This project requires JDK 11+
+Maven dependencies in the project:
+* [Lombok](https://github.com/rzwitserloot/lombok): 1.18.16
+
+##Features
+The list of the features currently implemented in the project:
+* [Rcon](https://developer.valvesoftware.com/wiki/Source_RCON_Protocol):
+ * Authentication to server with IP and Port
+ * Executing commands to the server and receiving answer
+ * Receiving commands from the server **without sending commands**. Listing to game console
+ * Support of multi-package answers
+* [Server Queries](https://developer.valvesoftware.com/wiki/Server_queries)
+ * A2S_INFO
+ * A2S_PLAYER
+ * A2S_RULES
+ * A2S_PING and A2S_SERVERQUERY_GETCHALLENGE are depricated
+
+##Installation
+Download project from release page of the project
+
+or
+
+Add dependency to your project manager
+**Maven**:
+```xml
+
+ com.antonio112009
+ steam4j
+ 1.0.0
+
+```
+
+## Code examples
+
+### Rcon examples:
+Execute single command:
+```java
+public class SendingSingleCommand {
+
+ public static void main(String[] args) {
+ Rcon rcon = new Rcon("0.0.0.0", 21114);
+ rcon.openStream();
+ boolean isAuthenticated = rcon.authenticate(password);
+ if(isAuthenticated) {
+ String answerFromServer = rcon.sendCommand("ListPlayers");
+ System.out.println("Answer: " + answerFromServer);
+ }
+ rcon.closeStream(); //optional if it's in the end of the program
+ }
+
+}
+```
+
+Execute multiple command:
+```java
+public class SendingMultipleCommand {
+
+ public static void main(String[] args) {
+ Rcon rcon = new Rcon("0.0.0.0", 21114);
+ rcon.openStream();
+ boolean isAuthenticated = rcon.authenticate(password);
+ if(isAuthenticated) {
+ System.out.println("Answer1: " + rcon.sendCommand("ListPlayers"));
+ System.out.println("Answer2: " + rcon.sendCommand("GetCurrentScore"));
+ System.out.println("Answer3: " + rcon.sendCommand("ChatToAll Hello world!"));
+ System.out.println("Answer: " + answerFromServer);
+ }
+ rcon.closeStream(); //optional if it's in the end of the program
+ }
+
+}
+```
+
+Receiving non-stop messages from a server (no execution of commands). Usually console logs:
+```java
+public class ReceiveServerLogs {
+
+ public static void main(String[] args) {
+ Rcon rcon = new Rcon("0.0.0.0", 21114);
+ rcon.openStream();
+ boolean isAuthenticated = rcon.authenticate(password);
+ while (isAuthenticated) {
+ try {
+ System.out.println("Answer: " + rcon.receivingServerMessages());
+ } catch (IOException e) {
+ e.printStackTrace();
+ rcon.closeStream(); //optional if it's in the end of the program
+ break;
+ }
+ }
+ }
+
+}
+```
+
+### Server Queries (A2S):
+All objects represent response format of data that are shown in details on the [official Valve developer page](https://developer.valvesoftware.com/wiki/Server_queries).
+
+### Server information
+Getting information of the server. Read more [here](https://developer.valvesoftware.com/wiki/Server_queries#A2S_INFO)
+```java
+public class GetServerInformation {
+
+ public static void main(String[] args) {
+ A2s a2s = new A2S("0.0.0.0", 27166);
+ ServerInfo serverInfo = a2S.getServerInfo();
+ System.out.println("Result:\n" + serverInfo.toString());
+ }
+
+}
+```
+
+### Server players
+Getting information of the server. Read more [here](https://developer.valvesoftware.com/wiki/Server_queries#A2S_PLAYER)
+```java
+public class GetServerInformation {
+
+ public static void main(String[] args) {
+ A2s a2s = new A2S("0.0.0.0", 27166);
+ Players players = a2S.getPlayers();
+ System.out.println("Result:\n" + players.toString());
+ }
+
+}
+```
+
+### Server rules
+Getting information of the server. Read more [here](https://developer.valvesoftware.com/wiki/Server_queries#A2S_RULES)
+```java
+public class GetServerInformation {
+
+ public static void main(String[] args) {
+ A2s a2s = new A2S("0.0.0.0", 27166);
+ Rules rules = a2S.getRules();
+ System.out.println("Result:\n" + rules.toString());
+ }
+
+}
+```
+
+## Contribution
+The contribution template and format is currently under development. Anyway, you are welcome to contribute this project.
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..6cdda5c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,55 @@
+
+
+ 4.0.0
+
+ com.antonio112009
+ steam4j
+ 1.0.0
+ jar
+
+
+ UTF-8
+ UTF-8
+ 11
+ 11
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.16
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.7.0
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ 11
+
+
+
+
+
+
+
+ github
+ GitHub Antonio112009 Apache Maven Packages
+ https://maven.pkg.github.com/Antonio112009/Steam4J
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/antonio112009/steam4j/core/a2s/A2S.java b/src/main/java/com/antonio112009/steam4j/core/a2s/A2S.java
new file mode 100644
index 0000000..482c865
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/a2s/A2S.java
@@ -0,0 +1,313 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.a2s;
+
+import com.antonio112009.steam4j.core.a2s.model.info.ServerInfo;
+import com.antonio112009.steam4j.core.a2s.model.player.Player;
+import com.antonio112009.steam4j.core.a2s.model.player.Players;
+import com.antonio112009.steam4j.core.a2s.model.rule.Rule;
+import com.antonio112009.steam4j.core.a2s.model.rule.Rules;
+import com.antonio112009.steam4j.core.a2s.type.A2SType;
+import com.antonio112009.steam4j.core.a2s.util.Converter;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.util.Arrays;
+
+public class A2S {
+
+ private String serverIp;
+ private int port;
+ private DatagramSocket datagramSocket;
+ private int index;
+
+ public A2S(String serverIp, int port) {
+ this.serverIp = serverIp;
+ this.port = port;
+ }
+
+
+ private byte[] sendData(byte[] data) throws IOException {
+ datagramSocket = new DatagramSocket();
+
+ InetAddress address = InetAddress.getByName(serverIp);
+ DatagramPacket datagramPacket = new DatagramPacket(data, data.length, address, port);
+ datagramSocket.setSoTimeout(500);
+
+ datagramSocket.send(datagramPacket);
+
+ // Steam uses a packet size of 1400 bytes + IP/UDP headers.
+ // If a request or response needs more packets for the data it starts the packets with an additional header.
+ byte[] receiveBuffer = new byte[1480];
+
+ DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
+ datagramSocket.receive(receivePacket);
+ return receivePacket.getData();
+ }
+
+
+ /**
+ * GET SERVER RULES
+ */
+ public Rules getRules() {
+ try {
+ byte[] data = sendData(Converter.hexStrToBinaryStr(A2SType.A2S_RULES));
+
+ // probably, store challenge in local variable
+ if(data[4] == (byte) 0x41) {
+ data = sendData(Converter.hexStrToBinaryStr(A2SType.A2S_RULES_REPLY + " " + Converter.binaryToString(Arrays.copyOfRange(data, 5,9))));
+ }
+
+ return convertResponseToRules(data);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+ // First 4 elements from the array - are header. It shows if packet is split or not.
+ private Rules convertResponseToRules(byte[] data) {
+ index = 4;
+
+ Rules rules = new Rules();
+ rules.setHeader(Converter.hexToAscii(Converter.byteToHex(data[index++])));
+ rules.setTotalRules(data[index++]);
+ index++;
+
+ for (int i = 0; i < rules.getTotalRules(); i++) {
+ try {
+ Rule rule = new Rule();
+ rule.setName(byteArrayToString(data));
+ rule.setValue(byteArrayToString(data));
+ rules.getRuleList().add(rule);
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ return rules;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /**
+ * GET PLAYERS
+ */
+ public Players getPlayers() {
+ try {
+ byte[] data = sendData(Converter.hexStrToBinaryStr(A2SType.A2S_PLAYER));
+
+ // probably, store challenge in local variable
+ if(data[4] == (byte) 0x41) {
+ data = sendData(Converter.hexStrToBinaryStr(A2SType.A2S_PLAYER_REPLY + " " + Converter.binaryToString(Arrays.copyOfRange(data, 5,9))));
+ }
+
+ return convertResponseToPlayers(data);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+
+ // First 4 elements from the array - are header. It shows if packet is split or not.
+ private Players convertResponseToPlayers(byte[] data) {
+ index = 4;
+
+ Players players = new Players();
+ players.setHeader(Converter.hexToAscii(Converter.byteToHex(data[index++])));
+ players.setTotalPlayers(data[index++]);
+
+ for (int i = 0; i < players.getTotalPlayers(); i++) {
+ try {
+ Player player = new Player();
+
+ player.setIndex(data[index++]);
+ player.setName(byteArrayToString(data));
+ player.setScore(calculateLong(data));
+ player.setDuration(calculateFloat(data));
+
+ players.getPlayerList().add(player);
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ //TODO: add error handler
+ }
+ }
+
+ return players;
+ }
+
+
+
+
+
+
+
+
+ /**
+ * GET SERVER INFO
+ * @return
+ */
+ public ServerInfo getServerInfo() {
+ try {
+ byte[] data = sendData(Converter.hexStrToBinaryStr(A2SType.A2S_INFO));
+
+ if (data[4] == (byte) 0x6d) {
+// oldSourceServer(resBytes, jsonObject);
+ } else {
+ return convertResponseToServerInfo(data, false);
+// sourceServer(resBytes, jsonObject);
+ }
+ return null;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+ // First 4 elements from the array - are header. It shows if packet is split or not.
+ private ServerInfo convertResponseToServerInfo(byte[] data, boolean addEDF) {
+ index = 4;
+
+ ServerInfo serverInfo = new ServerInfo();
+
+ serverInfo.setHeader(Converter.hexToAscii(Converter.byteToHex(data[index++])));
+
+ // TODO: possibly getting wrong data
+ serverInfo.setProtocol(data[index++]);
+ serverInfo.setName(byteArrayToString(data));
+ serverInfo.setMap(byteArrayToString(data));
+ serverInfo.setFolder(byteArrayToString(data));
+ serverInfo.setGame(byteArrayToString(data));
+
+ // space with 2 zero elements
+ index += 2;
+ serverInfo.setPlayers(data[index++]);
+ serverInfo.setMaxPlayers(data[index++]);
+ index++;
+ serverInfo.setServerType(Converter.hexToAscii(Converter.byteToHex(data[index++])));
+ serverInfo.setEnvironment(Converter.hexToAscii(Converter.byteToHex(data[index++])));
+ serverInfo.setVisibility(data[index++]);
+ serverInfo.setVac(data[index++]);
+ serverInfo.setVersion(byteArrayToString(data));
+
+ // TODO: modify later
+ // Work with EDF
+ while (data[index] != 0 && addEDF) {
+ switch (Converter.byteToHex(data[index++])) {
+ case "80": {
+ System.out.println("80");
+ index++;
+ }
+ case "10": {
+ System.out.println("10");
+ index++;
+ }
+ case "40": {
+ System.out.println("40");
+ index++;
+ }
+ case "20": {
+ System.out.println("20");
+ serverInfo.setKeywords(byteArrayToString(data));
+ }
+ case "01": {
+ System.out.println("1");
+ StringBuilder gameId = new StringBuilder();
+ for (int i = 0; i < 4; i++) {
+ gameId.append(Converter.byteToHex(data[index + i]));
+ }
+ serverInfo.setGameId(Long.parseLong(gameId.toString(), 16));
+ index += 5;
+ }
+ default: {
+ index++;
+ }
+ }
+ }
+
+
+ // adding data left in the message in case of broken query from developers of the game)
+ serverInfo.setRestDataLeft(Arrays.copyOfRange(data, index, data.length));
+ return serverInfo;
+ }
+
+
+
+
+
+
+
+ private String byteArrayToString (byte[] data) {
+ byte[] tmp = new byte[1000];
+ int indexTmp = 0;
+ while (data[index] != 0) {
+ tmp[indexTmp] = data[index];
+ indexTmp++;
+ index++;
+ }
+ index++;
+ return Converter.byteToString(tmp);
+ }
+
+ private long calculateLong(byte[] data) {
+ long longi = 0;
+ for (int j = 0; j < 4; j++, index++) {
+ longi = longi | ((long) data[index] << 8 * j);
+ }
+ return longi;
+ }
+
+ private float calculateFloat(byte[] data) {
+ byte[] tmp = new byte[4];
+ for (int j = 0; j < 4; j++, index++) {
+ tmp[j] = data[index];
+ }
+
+ int accum = 0;
+ accum = accum | (tmp[0] & 0xff);
+ accum = accum | (tmp[1] & 0xff) << 8;
+ accum = accum | (tmp[2] & 0xff) << 16;
+ accum = accum | (tmp[3] & 0xff) << 24;
+
+ return Float.intBitsToFloat(accum) * 1;
+ }
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/a2s/model/info/ServerInfo.java b/src/main/java/com/antonio112009/steam4j/core/a2s/model/info/ServerInfo.java
new file mode 100644
index 0000000..83ee6b0
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/a2s/model/info/ServerInfo.java
@@ -0,0 +1,61 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.a2s.model.info;
+
+import lombok.Data;
+
+@Data
+public class ServerInfo {
+
+ private String header;
+ private byte protocol;
+ private String name;
+ private String map;
+ private String folder;
+ private String game;
+ private short id;
+ private int players;
+ private int maxPlayers;
+ private int bots;
+ private String serverType; // https://developer.valvesoftware.com/wiki/Server_queries#A2S_INFO
+ private String environment; // https://developer.valvesoftware.com/wiki/Server_queries#A2S_INFO
+ private byte visibility;
+ private byte vac;
+
+ // If server running "The Ship"
+ //TODO: add Ship support
+
+ private String version;
+
+ //Extra Data Flag (EDF)
+ private int serverGamePort; // 0x80
+ private long steamId; // 0x10
+ private long spectatorPort; // 0x40
+ private long spectatorName; // 0x40
+ private String keywords; // 0x20
+ private long gameId; // 0x01
+
+ private byte[] restDataLeft;
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/a2s/model/player/Player.java b/src/main/java/com/antonio112009/steam4j/core/a2s/model/player/Player.java
new file mode 100644
index 0000000..a638c06
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/a2s/model/player/Player.java
@@ -0,0 +1,36 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.a2s.model.player;
+
+import lombok.Data;
+
+@Data
+public class Player {
+
+ private int index;
+ private String name;
+ private long score;
+ private float duration;
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/a2s/model/player/Players.java b/src/main/java/com/antonio112009/steam4j/core/a2s/model/player/Players.java
new file mode 100644
index 0000000..597b8ea
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/a2s/model/player/Players.java
@@ -0,0 +1,38 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.a2s.model.player;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class Players {
+
+ private String header;
+ private int totalPlayers;
+ private List playerList = new ArrayList<>();
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/a2s/model/rule/Rule.java b/src/main/java/com/antonio112009/steam4j/core/a2s/model/rule/Rule.java
new file mode 100644
index 0000000..04d598c
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/a2s/model/rule/Rule.java
@@ -0,0 +1,33 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.a2s.model.rule;
+
+import lombok.Data;
+
+@Data
+public class Rule {
+ private String name;
+ private String value;
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/a2s/model/rule/Rules.java b/src/main/java/com/antonio112009/steam4j/core/a2s/model/rule/Rules.java
new file mode 100644
index 0000000..fcb4cce
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/a2s/model/rule/Rules.java
@@ -0,0 +1,38 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.a2s.model.rule;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class Rules {
+
+ private String header;
+ private int totalRules;
+ List ruleList = new ArrayList<>();
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/a2s/packet/A2SPacket.java b/src/main/java/com/antonio112009/steam4j/core/a2s/packet/A2SPacket.java
new file mode 100644
index 0000000..3067e52
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/a2s/packet/A2SPacket.java
@@ -0,0 +1,28 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.a2s.packet;
+
+public class A2SPacket {
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/a2s/type/A2SType.java b/src/main/java/com/antonio112009/steam4j/core/a2s/type/A2SType.java
new file mode 100644
index 0000000..0a3c796
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/a2s/type/A2SType.java
@@ -0,0 +1,35 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.a2s.type;
+
+public class A2SType {
+ public static final String A2S_INFO = "FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 6E 65 20 51 75 65 72 79 00";
+ public static final String A2S_PLAYER = "FF FF FF FF 55 FF FF FF FF";
+ public static final String A2S_PLAYER_REPLY = "FF FF FF FF 55";
+ public static final String A2S_RULES = "FF FF FF FF 56 FF FF FF FF";
+ public static final String A2S_RULES_REPLY = "FF FF FF FF 56";
+ public static final String A2S_SERVERQUERY_GETCHALLENGE = "FF FF FF FF 57";
+
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/a2s/util/Converter.java b/src/main/java/com/antonio112009/steam4j/core/a2s/util/Converter.java
new file mode 100644
index 0000000..15cd471
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/a2s/util/Converter.java
@@ -0,0 +1,97 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.a2s.util;
+
+public class Converter {
+
+ public static String byteToString(byte[] src) {
+ try {
+ int length = 0;
+ for (int i = 0; i < src.length; ++i) {
+ if (src[i] == 0) {
+ length = i;
+ break;
+ }
+ }
+ return new String(src, 0, length, "UTF-8");
+ } catch (Exception e) {
+// log.error(e.toString());
+ return "";
+ }
+ }
+
+ public static byte[] hexStrToBinaryStr(String hexString) {
+ if (hexString == null) return null;
+
+ String[] tmp = hexString.split(" ");
+ byte[] tmpBytes = new byte[tmp.length];
+ int i = 0;
+ for (String b : tmp) {
+ if (b.equals("FF")) {
+ tmpBytes[i++] = -1;
+ } else {
+ tmpBytes[i++] = Integer.valueOf(b, 16).byteValue();
+ }
+ }
+ return tmpBytes;
+ }
+
+ public static String binaryToString(byte[] data) {
+ try {
+ char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ StringBuilder stringBuffer = new StringBuilder();
+ for (byte datum : data) {
+ stringBuffer.append(HEX_CHAR[(datum < 0 ? datum + 256 : datum) / 16]);
+ stringBuffer.append(HEX_CHAR[(datum < 0 ? datum + 256 : datum) % 16]);
+ stringBuffer.append(" ");
+ }
+ return stringBuffer.toString();
+ } catch (Exception e) {
+ // TODO: handle exception
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+ public static String byteToHex(byte input) {
+ char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ return String.valueOf(HEX_CHAR[(input < 0 ? input + 256 : input) / 16]) +
+ HEX_CHAR[(input < 0 ? input + 256 : input) % 16];
+ }
+
+
+ // POSSIBLY NO NEED!!!
+ public static String hexToAscii(String hexStr) {
+ StringBuilder output = new StringBuilder();
+
+ for (int i = 0; i < hexStr.length(); i += 2) {
+ String str = hexStr.substring(i, i + 2);
+ output.append((char) Integer.parseInt(str, 16));
+ }
+
+ return output.toString();
+ }
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/rcon/Rcon.java b/src/main/java/com/antonio112009/steam4j/core/rcon/Rcon.java
new file mode 100644
index 0000000..7436cfc
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/rcon/Rcon.java
@@ -0,0 +1,164 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.rcon;
+
+import com.antonio112009.steam4j.core.rcon.packet.RconPacket;
+import com.antonio112009.steam4j.core.rcon.type.RconPacketType;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.nio.ByteBuffer;
+
+//@Slf4j
+public class Rcon {
+
+ private String serverIp;
+ private int serverPort;
+
+ private Socket socket;
+ private static final int RESPONSE_TIMEOUT = 1000;
+ private boolean authenticated = false;
+
+ public Rcon(String serverIp, int serverPort) {
+ this.serverIp = serverIp;
+ this.serverPort = serverPort;
+ }
+
+
+ public boolean openStream() {
+ try {
+ socket = new Socket(serverIp, serverPort);
+ socket.setSoTimeout(RESPONSE_TIMEOUT);
+ return socket.isConnected();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+// log.error("Error with server connection: " + e.getMessage());
+ return false;
+ }
+ }
+
+
+
+ // DO NOT MODIFY!!!!
+ public boolean authenticate(String password) {
+ RconPacket rconPacket = new RconPacket();
+ int id = (int) (Math.random() * 9999999) + 1;
+ byte[] authRequest = rconPacket.sendPacket(id, RconPacketType.SERVERDATA_AUTH, password);
+
+ ByteBuffer response;
+ try {
+ socket.getOutputStream().write(authRequest);
+
+ rconPacket.receivePacket(socket.getInputStream()); //junk response packet
+ response = rconPacket.receivePacket(socket.getInputStream());
+
+ if ((response.getInt(4) == id) && (response.getInt(8) == RconPacketType.SERVERDATA_AUTH_RESPONSE))
+ authenticated = true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return authenticated;
+ }
+
+
+
+
+ public String sendCommand(String command) {
+ try {
+ ByteBuffer[] response = sendToServer(command);
+ if (response != null) {
+ return RconPacket.assemblePackets(response);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+
+ private ByteBuffer[] sendToServer(String command) {
+ RconPacket rconPacket = new RconPacket();
+ int id = (int) (Math.random() * (9999999) + 1);
+
+ byte[] request = rconPacket.sendPacket(id, RconPacketType.SERVERDATA_EXECCOMMAND, command);
+ byte[] emptyRequest = rconPacket.sendEmptyPacket(id, RconPacketType.SERVERDATA_RESPONSE_VALUE);
+
+ ByteBuffer[] resp = new ByteBuffer[4096];
+ int i = 0;
+
+ try {
+ socket.getOutputStream().write(request);
+ socket.getOutputStream().write(emptyRequest);
+
+ while(true) {
+ ByteBuffer response = rconPacket.receivePacket(socket.getInputStream());
+ if(response != null) {
+ if (response.getInt(4) == id) {
+ if (RconPacket.getBodySinglePacket(response).equals("")) {
+ rconPacket.receivePacket(socket.getInputStream());
+ break;
+ } else {
+ resp[i] = response;
+ }
+ i++;
+ }
+ }
+ }
+
+ return resp;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+ public String receivingServerMessages() throws IOException{
+ RconPacket rconPacket = new RconPacket();
+
+ try {
+ ByteBuffer response = rconPacket.receivePacket(socket.getInputStream());
+ if(response != null) {
+ return RconPacket.getBodySinglePacket(response);
+ }
+
+ } catch (SocketTimeoutException ignores) {
+ }
+ return null;
+ }
+
+ public void closeStream() {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/rcon/packet/RconPacket.java b/src/main/java/com/antonio112009/steam4j/core/rcon/packet/RconPacket.java
new file mode 100644
index 0000000..40c5fee
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/rcon/packet/RconPacket.java
@@ -0,0 +1,126 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.rcon.packet;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Basic Packet Structure
+ *
+ * Size: 32-bit little-endian Signed Integer
+ * ID: 32-bit little-endian Signed Integer (4 Bytes)
+ * Type: 32-bit little-endian Signed Integer (4 Bytes)
+ * Body: Null-terminated ASCII String (at least 1 Byte)
+ * Empty String: Null-terminated ASCII String (1 Byte)
+ */
+//@Slf4j
+public class RconPacket {
+
+ private ByteBuffer payload = null;
+
+
+ /**
+ * Setting size of the buffer.
+ *
+ * From valve's wiki:
+ * Since the only one of these values that can change in length is the body,
+ * an easy way to calculate the size of a packet is to find
+ * the byte-length of the packet body, then add 10 to it.
+ *
+ */
+ public byte[] sendPacket(int id, int type, String body) {
+ payload = ByteBuffer.allocate(body.getBytes(StandardCharsets.UTF_8).length + 14);
+ payload.order(ByteOrder.LITTLE_ENDIAN);
+
+ // Setting Size
+ payload.putInt(body.getBytes(StandardCharsets.UTF_8).length + 10);
+
+ // Setting ID
+ payload.putInt(id);
+
+ // Setting Type
+ payload.putInt(type);
+
+ // Setting Body
+ payload.put(body.getBytes());
+
+ // Adding two null bytes at the end
+ payload.put((byte) 0x00);
+ payload.put((byte) 0x00);
+ return payload.array();
+ }
+
+ public byte[] sendEmptyPacket(int id, int type) {
+ return sendPacket(id, type, "");
+ }
+
+
+ public ByteBuffer receivePacket(InputStream inputStream) throws IOException {
+ payload = ByteBuffer.allocate(4096);
+ payload.order(ByteOrder.LITTLE_ENDIAN);
+
+ byte[] length = new byte[4];
+ if(inputStream.read(length, 0, 4) == 4) {
+ if(length[0] == 0)
+ return null; // TODO: модернизировать
+ payload.put(length);
+ for (int i = 0; i < payload.getInt(0); i++) {
+ payload.put((byte) inputStream.read());
+ }
+ return payload;
+ } else {
+ return null;
+ }
+ }
+
+
+
+
+ public static String assemblePackets(ByteBuffer[] packets) {
+ // Return the text from all the response packets together
+ StringBuilder response = new StringBuilder();
+
+ for (ByteBuffer packet : packets) {
+ response.append(getBodySinglePacket(packet));
+ }
+ return response.toString();
+ }
+
+ public static String getBodySinglePacket(ByteBuffer packet) {
+ if (packet != null) {
+ return new String(packet.array(), 12, packet.position() - 14);
+// log.debug(response.toString());
+ } else {
+ return "";
+ }
+ }
+
+
+}
diff --git a/src/main/java/com/antonio112009/steam4j/core/rcon/type/RconPacketType.java b/src/main/java/com/antonio112009/steam4j/core/rcon/type/RconPacketType.java
new file mode 100644
index 0000000..73cd9e9
--- /dev/null
+++ b/src/main/java/com/antonio112009/steam4j/core/rcon/type/RconPacketType.java
@@ -0,0 +1,32 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2021 Anton Rogalskiy and Steam4J contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.antonio112009.steam4j.core.rcon.type;
+
+public class RconPacketType {
+ public final static byte SERVERDATA_AUTH = 3;
+ public final static byte SERVERDATA_EXECCOMMAND = 2;
+ public final static byte SERVERDATA_AUTH_RESPONSE = 2;
+ public final static byte SERVERDATA_RESPONSE_VALUE = 0;
+}