diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml
new file mode 100644
index 0000000..1b29d8d
--- /dev/null
+++ b/.github/workflows/ci-cd.yml
@@ -0,0 +1,51 @@
+name: Java CI/CD
+
+on:
+ push:
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - '**'
+
+jobs:
+ build-and-test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 25
+ uses: actions/setup-java@v4
+ with:
+ java-version: '25'
+ distribution: 'temurin'
+ cache: maven
+ - name: Set version
+ run: |
+ if [[ $GITHUB_REF == refs/tags/* ]]; then
+ echo "REVISION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
+ else
+ echo "REVISION=0.0.0-SNAPSHOT" >> $GITHUB_ENV
+ fi
+ - name: Build with Maven
+ run: mvn -B package -Drevision=${{ env.REVISION }} --file pom.xml
+
+ publish:
+ if: startsWith(github.ref, 'refs/tags/')
+ needs: build-and-test
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 25
+ uses: actions/setup-java@v4
+ with:
+ java-version: '25'
+ distribution: 'temurin'
+ server-id: github
+ settings-path: ${{ github.workspace }}
+ - name: Publish to GitHub Packages
+ run: mvn -B deploy -DskipTests -Drevision=${{ github.ref_name }} --file pom.xml
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 524f096..6a2f002 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,5 @@
-# Compiled class file
-*.class
+# IDE
+/.idea/
-# Log file
-*.log
-
-# BlueJ files
-*.ctxt
-
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
-
-# Package Files #
-*.jar
-*.war
-*.nar
-*.ear
-*.zip
-*.tar.gz
-*.rar
-
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
-replay_pid*
+# Build
+/target/
\ No newline at end of file
diff --git a/LICENSE b/LICENSE.md
similarity index 100%
rename from LICENSE
rename to LICENSE.md
diff --git a/README.md b/README.md
index 0faeba2..2cf27c9 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,129 @@
# a2s-java
-Valve Steam Query Protocol implementation for Java
+
+A Valve Steam Query Protocol (A2S) implementation for Java using Netty.
+
+This library allows you to query game servers that implement the Source Engine Query protocol, such as Counter-Strike, Team Fortress 2, Rust, ARK, and many others.
+
+> [!NOTE]
+> This code is based on and used from [yeetus-desastroesus/A2S-Java](https://github.com/yeetus-desastroesus/A2S-Java).
+
+## Features
+
+- **A2S_INFO**: Get server information (name, map, player count, etc.).
+- **A2S_PLAYER**: Get detailed list of players currently on the server.
+- **A2S_RULES**: Get server rules/CVars.
+- **Asynchronous**: Built on Netty for high-performance, non-blocking I/O.
+- **Server Implementation**: Includes a basic A2S server implementation for testing or mocking.
+
+## Installation
+
+The library is published on GitHub Packages. To use it, you need to configure your build tool to include the GitHub Maven repository.
+
+### Maven
+
+1. Add the following repository to your `pom.xml`:
+
+```xml
+
+
+ github
+ https://maven.pkg.github.com/g-portal/a2s-java
+
+
+```
+
+2. Add the following dependency to your `pom.xml`:
+
+```xml
+
+ com.gportal
+ a2s
+ 1.0.0
+
+```
+
+### Gradle
+
+1. Add the following repository to your `build.gradle`:
+
+```gradle
+repositories {
+ maven {
+ url = uri("https://maven.pkg.github.com/g-portal/a2s-java")
+ }
+}
+```
+
+2. Add the following to your `build.gradle` dependencies:
+
+```gradle
+dependencies {
+ implementation 'com.gportal:a2s:1.0.0' // Use the desired release tag version
+}
+```
+
+## Usage
+
+### Querying a Server (Client)
+
+```java
+import com.gportal.source.query.QueryClient;
+import com.gportal.source.query.ServerInfo;
+import com.gportal.source.query.PlayerInfo;
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+public class Example {
+ public static void main(String[] args) throws Exception {
+ QueryClient client = new QueryClient();
+ InetSocketAddress address = new InetSocketAddress("127.0.0.1", 27015);
+
+ // Query Server Info
+ CompletableFuture infoFuture = client.queryServer(address);
+ infoFuture.thenAccept(info -> System.out.println("Server Name: " + info.name()));
+
+ // Query Players
+ CompletableFuture> playersFuture = client.queryPlayers(address);
+ playersFuture.thenAccept(players -> players.forEach(p -> System.out.println("Player: " + p.name())));
+
+ // Query Rules
+ CompletableFuture