Skip to content

Commit

Permalink
Finished readme + Minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanpoland committed May 12, 2024
1 parent aaccd4e commit c41619b
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 69 deletions.
29 changes: 19 additions & 10 deletions BuntDB/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"net/http"
"time"

"github.com/googollee/go-socket.io"
socketio "github.com/zhouhui8915/go-socket.io-client"
"github.com/tidwall/buntdb"
)

Expand All @@ -20,27 +20,36 @@ func main() {
})

// Listen on port 8000
ln, err := net.Listen("tcp", ":3001")
ln, err := net.Listen("tcp", ":3003")
if err != nil {
log.Fatal(err)
}
defer ln.Close()

// Initialize a new server
server := socketio.NewServer(nil)
server, err := socketio.NewClient([]string{"http://localhost:3001"}, nil)
if err != nil {
log.Fatal(err)
fmt.Println("Connected to Socket.IO server: ", err)
} else {
fmt.Println("Server listening on port 3001")
fmt.Println("Connected to Socket.IO server")
}

// Handle '/socket.io/' endpoint
http.Handle("/socket.io/", server)
go server.On("updateResult", func(data string) {
fmt.Println("Received update result:", data)
})

go http.Serve(ln, nil)

// Emit "DBUp" event
go func() {
time.Sleep(2 * time.Second) // Assuming 2 seconds for the server to start
server.Emit("DBUp", "")
}()

// Handle events
server.OnEvent("/", "update", func(s socketio.Conn, txData string) {
fmt.Println("Received update request:", txData)
server.On("update", func(data string) {
fmt.Println("Received update request:", data)

// Open the database (use in-memory for this example)
db, err := buntdb.Open(":memory:")
Expand All @@ -51,7 +60,7 @@ func main() {

start := time.Now()
err = db.Update(func(tx *buntdb.Tx) error {
// Perform transaction here based on txData
// Perform transaction here based on data
return nil
})
if err != nil {
Expand All @@ -61,7 +70,7 @@ func main() {
elapsed := time.Since(start)

// Emit performance measurement
s.Emit("updateResult", fmt.Sprintf("Update transaction took: %s", elapsed))
server.Emit("updateResult", fmt.Sprintf("Update transaction took: %s", elapsed))
})

// Run forever
Expand Down
5 changes: 0 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,3 @@ socketioxide = "0.13.0"
tokio = { version = "1.37.0", features = ["rt", "net", "rt-multi-thread"] }
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
rust_socketio = { version = "*", features = ["async"] }
openssl = "0.10.64"
openssl-sys = "0.9.102"

[target.x86_64-unknown-linux-musl.dependencies]
3 changes: 1 addition & 2 deletions Dockerfile.golang
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ COPY ./ /go
# RUN go build -o horizon-memory-db .

# Specify the command to run the GoLang application
#CMD ["go","run","/go/BuntBD/."]
CMD ["sleep", "infinity"]
CMD ["go","run","/go/BuntBD/."]
157 changes: 140 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,145 @@
# Horizon
An easily scalable game server
## 1. Introduction

```RUST
use tracing::info;
Helpes append .route to a specific **mutable** variable so you don't have to.
Horizon is a custom game server software designed to facilitate seamless interaction between Unreal Engine 5 (UE5) and client applications through socket.io. It provides a scalable and customizable solution for hosting multiplayer games and managing real-time communication between players and a limitless number of game servers or "Hosts".

The first parameter is the variable itself; the value of `axum::Router::new()`.
The second value is the endpoint, eg "/".
The third value is what to return back.
### Synchronized Game Server Architecture

# Example
#### Horizon Parent-Child Socket Sync

```rust
let mut app = axum::Router::new()
.layer(layer);
Horizon utilizes a sophisticated Parent-Child socket synchronization mechanism to ensure seamless coordination between multiple Horizon instances, effectively creating a unified game server environment with minimal latency.

##### How it Works

- **Parent-Child Relationship**: In the Horizon architecture, one instance acts as the Parent node, while others serve as Child nodes. The Parent node orchestrates and synchronizes actions across all Child nodes.

- **Socket Communication**: Horizon employs socket.io for real-time communication between Parent and Child nodes. This allows for near-instantaneous data transmission, crucial for maintaining synchronization in fast-paced multiplayer games.

- **Data Exchange Protocol**: The Parent node continuously sends updates to Child nodes regarding game state, player actions, and other relevant information. Conversely, Child nodes report back to the Parent node, ensuring bidirectional communication for accurate synchronization.

- **Latency Optimization**: To achieve near-zero latency, Horizon optimizes data transmission by minimizing overhead and prioritizing critical updates. This ensures that actions performed on one Child node propagate swiftly to all others, maintaining a cohesive game experience for all players.

##### Benefits

- **Scalability**: The Parent-Child architecture allows Horizon to scale effortlessly, accommodating a growing player base without sacrificing performance.

- **Fault Tolerance**: In the event of node failure, the Parent node seamlessly redistributes responsibilities to remaining Child nodes, ensuring uninterrupted gameplay for players.

- **Consistency**: By synchronizing game state across all instances, Horizon guarantees a consistent experience for all players, regardless of their geographical location or server proximity.

##### Implementation Details

- **Configuration**: Administrators can fine-tune synchronization parameters via the `server-config.json` file, adjusting settings such as synchronization frequency and data prioritization to suit specific requirements.

- **Monitoring**: Horizon provides built-in monitoring tools to track synchronization performance, allowing administrators to identify and address any potential bottlenecks or issues promptly.

#### Conclusion

The Horizon Parent-Child socket synchronization mechanism revolutionizes multiplayer game server architecture, offering unparalleled scalability, fault tolerance, and consistency. By leveraging real-time communication and optimization techniques, Horizon ensures that all players experience a seamless and immersive gaming environment, regardless of the complexity or scale of the game world.

## 2. Installation

#### Prerequisites
Before installing Horizon, ensure that you have the following prerequisites:

- Docker installed on your system.
- Git for cloning the Horizon repository.
- Basic understanding of Docker and containerized applications.

#### Installation Steps

1. Clone the Horizon repository from GitHub:

```bash
git clone https://github.com/your_username/Horizon.git
```

2. Navigate to the project directory:

```bash
cd Horizon
```

3. Build and deploy the horizon service via docker-compose:

```bash
docker-compose up --build
```

4. Follow the prompts to configure any necessary settings in the `server-config.json` file

For more detailed instructions and troubleshooting tips, refer to the [Installation Guide](installation.md).

## 3. Configuration

Horizon's configuration revolves around Docker and environment variables. Here's an overview of key configuration files:

- `compose.yaml`: Defines the Docker services, networks, and volumes for running Horizon.
- `Dockerfile`: Specifies the environment and dependencies for the Horizon server container.
- `start.sh`: Contains startup commands for launching the server.
- `server-config.json`: Contains Horizon server configurations

To customize Horizon for your specific needs, modify these files according to your requirements. Refer to the [Configuration Guide](configuration.md) for detailed instructions and best practices.

## 4. Usage

### Starting the Server

To start the Horizon server, execute the following command (This assumes you have already [Built the Horizon server](####Installation-Steps)):

```bash
./start.sh
```

This script initializes the Docker containers and launches the server. Once started, you can connect to the server using socket.io clients or integrate it with your Unreal Engine 5 project.

### Managing the Server manually
You can avoid using the pre-built scripts to manage your server by managing it directly via docker-compose.

- Use `docker-compose` commands to manage the server lifecycle (e.g., `docker-compose up`, `docker-compose down`).
- Monitor server logs for debugging and performance analysis.

For more usage instructions and advanced features, see the [Usage Guide](usage.md).

## 5. Development

### Project Structure

The Horizon project directory consists of several key components:

- `src/`: Contains source code for the Horizon server.
- `horizon-physics-engine/`: Additional modules or plugins for extended functionality.
- `BuntDB/`: Database-related files and configurations.
- Other configuration files and scripts for Docker and environment setup.

### Contribution Guidelines

- Follow the project's coding standards and conventions.
- Submit pull requests for proposed changes or enhancements.
- Collaborate with the community on GitHub issues and discussions.
For detailed development instructions and guidelines, refer to the [Development Guide](development.md).
## 6. Additional Resources
### Community Support
- Join our Discord server or community forums for support and collaboration.
- Follow us on social media for updates and announcements.
### Documentation
- Explore the official Horizon documentation for in-depth guides and tutorials.
- Check out our GitHub repository for code samples and examples.
For more resources and helpful links, visit the [Additional Resources section](resources.md).
## 7. Troubleshooting
### Common Issues
- **Connection Errors**: Ensure that the server is running and accessible from client applications.
- **Dependency Problems**: Check Docker logs for any issues during container initialization.
- **Performance Bottlenecks**: Monitor server performance and optimize resource usage if necessary.
For troubleshooting tips and solutions to common problems, consult the [Troubleshooting Guide](troubleshooting.md).
define_routes!(app,
"/", "Hello, World!",
"/goodbye", "Goodbye, World!",
"/function", function());
```
3 changes: 2 additions & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ services:
dockerfile: Dockerfile.rust
ports:
- 3000:3000
- 3001:3001

horizon-memory-db:
build:
Expand All @@ -15,7 +16,7 @@ services:
depends_on:
- horizon-game-server
ports:
- 3001:3001
- 3003:3003

horizon-physics-engine:
build:
Expand Down
58 changes: 24 additions & 34 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use socketioxide::{
extract::SocketRef,
SocketIo,
};
use rust_socketio::{ClientBuilder, Payload, RawClient};

use tracing::info;

Expand Down Expand Up @@ -44,64 +43,55 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("+-----------------------------------------------------------------------------------------+");
println!("");

tokio::try_join!(/*run_client(),*/ run_server())?;
tokio::try_join!(
run_internal_server(),
run_client_server()
)?;

Ok(())
}

async fn run_client() -> Result<(), Box<dyn std::error::Error>> {
// use SocketIo as SocketIoClient;
use rust_socketio::asynchronous::{Client, ClientBuilder};
// Emit a "update" event with transaction data to the Go server
let tx_data = "Transaction data goes here";
// socket.emit("update", &tx_data).await.expect("Failed to emit event");

async fn run_internal_server() -> Result<(), Box<dyn std::error::Error>> {
// Set up Socket.IO server for internal traffic on port 3001
let (layer, io) = SocketIo::new_layer();
// Connect to the Socket.IO server running on Go
// let socket = SocketIoClient::ClientBuilder::new("http://localhost:3001")
let socket = ClientBuilder::new("http://localhost:3001")
// let socket = <SocketIoClient<<_> as SocketIo>::ClientBuilder::new("http://localhost:3001")
.on("updateResult", |res, _| Box::pin(async move {
println!("Received update result: {:?}", res)
}))
.connect()
.await
.expect("Failed to connect to server");
// Handle incoming events from the GOLANG server (if any)
// socket.on("updateResult", |res| {
// println!("Received update result: {:?}", res);
// });

io.ns("DBUp", |s: SocketRef| {
println!("Received update result");
});

// Start the internal server
println!("Starting internal server");
let listener = tokio::net::TcpListener::bind("0.0.0.0:3001").await?;
println!("Internal server listening on port 3001");
axum::serve(listener, axum::Router::new().layer(layer)).await?;

Ok(())
}

async fn run_server() -> Result<(), Box<dyn std::error::Error>> {
// Set up Socket.IO server
async fn run_client_server() -> Result<(), Box<dyn std::error::Error>> {
// Set up Socket.IO server for clients on port 3000
let (layer, io) = SocketIo::new_layer();
// Register a handler for the default namespace

io.ns("/", |s: SocketRef| {
// Connection message
println!("New client connected!");

// For each "message" event received, send a "message-back" event with the "Hello World!" event
s.on("message", |s: SocketRef| {
s.emit("message-back", "Hello World!").ok();
});

// An event for printing data to the server console from client
s.on("ServerPrintToConsole", || {
println!("Server console print received from client");
});
});

// Create Axum app
// Create Axum app for client server
let mut app = axum::Router::new().layer(layer);
// Setup server home page in HTTP
define_routes!(app, "/", "Hello, World!");

// Start the server
println!("Starting server");
// Start the client server
println!("Starting client server");
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
println!("Stars Beyond dedicated server listening on all interfaces (0.0.0.0) via port 3000");
println!("Client server listening on port 3000");
axum::serve(listener, app).await?;

Ok(())
Expand Down

0 comments on commit c41619b

Please sign in to comment.