4 Commits

Author SHA1 Message Date
Smile Rex
1bb1e3bfd4 fix
All checks were successful
Create and publish a Docker image 🚀 / build-and-push-image (push) Successful in 3m25s
2026-01-21 13:10:15 +03:00
Smile Rex
9cd779fbea cors fix
All checks were successful
Create and publish a Docker image 🚀 / build-and-push-image (push) Successful in 1m9s
2026-01-21 12:36:25 +03:00
Smile Rex
3c989c33f8 new server
All checks were successful
Create and publish a Docker image 🚀 / build-and-push-image (push) Successful in 1m19s
2026-01-17 16:38:45 +03:00
Smile Rex
1c60264d1d add readme
All checks were successful
Create and publish a Docker image 🚀 / build-and-push-image (push) Successful in 1m8s
2026-01-15 11:55:05 +03:00
10 changed files with 156 additions and 85 deletions

View File

@@ -8,17 +8,17 @@ import (
)
func (h *Hub) readLoop(conn *websocket.Conn) {
handMessage := models.Message{Type: MSG_WELCOME}
_ = conn.WriteMessage(websocket.BinaryMessage, handMessage.Encode())
var player *models.Player
var id uint32
log.Println("client ws connected")
defer func() {
if player != nil {
h.removePlayer(player.ID)
log.Println("Player left:", player.ID)
}
conn.Close()
if id != 0 {
h.removeEntity(id)
log.Println("entity [player] removed:", id)
}
log.Println("client ws disconnected")
}()
for {
@@ -36,20 +36,32 @@ func (h *Hub) readLoop(conn *websocket.Conn) {
switch msg.Type {
case MSG_WELCOME:
if player != nil {
continue
reader := models.NewReader(msg.Payload)
log.Println("MSG_WELCOME received", &msg.Payload)
id = reader.ReadU32()
name := reader.ReadString()
if h.Entities[id] != nil {
h.ErrorMsg("Entity already exists", conn)
}
player = h.handShake(msg.Payload, conn)
log.Println("Player joined:", player.ID)
player := &models.Player{
BaseEntity: models.BaseEntity{ID: id},
Name: name,
}
h.addEntity(id, player)
h.Clients[id] = conn
log.Println("entity [player] added:", id)
case MSG_INPUT:
if player == nil {
continue
}
reader := models.NewReader(msg.Payload)
id := reader.ReadU32()
x := reader.ReadF32()
y := reader.ReadF32()
h.updatePosition(x, y, player)
z := reader.ReadF32()
h.updateEntityPosition(x, y, z, id)
log.Println(h.Entities)
}
}
}

31
controllers/entities.go Normal file
View File

@@ -0,0 +1,31 @@
package controllers
import "server/models"
func (h *Hub) addEntity(id uint32, entity models.Entity) {
h.Mu.Lock()
defer h.Mu.Unlock()
h.Entities[id] = entity
}
func (h *Hub) updateEntityPosition(x, y, z float32, entity_id uint32) {
h.Mu.Lock()
defer h.Mu.Unlock()
h.Entities[entity_id].SetPosition(x, y, z)
}
func (h *Hub) updateEntityRotation(yaw float32, entity_id uint32) {
h.Mu.Lock()
defer h.Mu.Unlock()
h.Entities[entity_id].SetYaw(yaw)
}
func (h *Hub) removeEntity(id uint32) {
h.Mu.Lock()
defer h.Mu.Unlock()
delete(h.Entities, id)
}

View File

@@ -5,16 +5,20 @@ import (
"net/http"
"server/models"
"sync"
"github.com/gorilla/websocket"
)
type Hub struct {
Players map[uint32]*models.Player
Mu sync.RWMutex
Entities map[uint32]models.Entity
Clients map[uint32]*websocket.Conn
Mu sync.RWMutex
}
func NewHub() *Hub {
return &Hub{
Players: make(map[uint32]*models.Player),
Entities: make(map[uint32]models.Entity),
Clients: make(map[uint32]*websocket.Conn),
}
}

14
controllers/msg.go Normal file
View File

@@ -0,0 +1,14 @@
package controllers
import (
"server/models"
"github.com/gorilla/websocket"
)
func (h *Hub) ErrorMsg(msg string, conn *websocket.Conn) {
wr := models.Writer{}
wr.WriteString(msg)
errMsg := &models.Message{Type: 9, Version: 1, Payload: wr.Bytes()}
conn.WriteMessage(websocket.BinaryMessage, errMsg.Encode())
}

View File

@@ -1,43 +0,0 @@
package controllers
import (
"server/models"
"github.com/gorilla/websocket"
)
func (h *Hub) handShake(msg []byte, conn *websocket.Conn) *models.Player {
reader := models.NewReader(msg)
newID := reader.ReadU32()
name := reader.ReadString()
player := &models.Player{
Entity: models.Entity{
Type: models.EntityPlayer,
ID: newID,
},
Name: name,
Conn: conn,
}
h.Mu.Lock()
h.Players[player.ID] = player
h.Mu.Unlock()
return player
}
func (h *Hub) updatePosition(x, y float32, player *models.Player) {
h.Mu.Lock()
defer h.Mu.Unlock()
player.X = x
player.Y = y
}
func (h *Hub) removePlayer(id uint32) {
h.Mu.Lock()
defer h.Mu.Unlock()
delete(h.Players, id)
}

View File

@@ -4,4 +4,5 @@ const (
MSG_WELCOME = 0
MSG_INPUT = 1
MSG_SNAPSHOT = 2
MSG_EVENT = 3
)

View File

@@ -12,15 +12,16 @@ func (h *Hub) broadcastSnapshot() {
defer h.Mu.RUnlock()
w := models.Writer{}
w.WriteU16(uint16(len(h.Players)))
w.WriteU16(uint16(len(h.Entities)))
for _, p := range h.Players {
w.WriteU32(p.ID)
w.WriteU8(uint8(models.EntityPlayer))
w.WriteF32(p.X)
w.WriteF32(p.Y)
w.WriteF32(p.Z)
w.WriteF32(p.Yaw)
for _, e := range h.Entities {
w.WriteU32(e.GetID())
w.WriteU8(uint8(e.GetType()))
x, y, z := e.GetPosition()
w.WriteF32(x)
w.WriteF32(y)
w.WriteF32(z)
w.WriteF32(e.GetYaw())
}
msg := models.Message{
@@ -29,9 +30,9 @@ func (h *Hub) broadcastSnapshot() {
Payload: w.Bytes(),
}
for _, p := range h.Players {
if p.Conn != nil {
_ = p.Conn.WriteMessage(websocket.BinaryMessage, msg.Encode())
for _, conn := range h.Clients {
if conn != nil {
_ = conn.WriteMessage(websocket.BinaryMessage, msg.Encode())
}
}
}

8
models/client.go Normal file
View File

@@ -0,0 +1,8 @@
package models
import "github.com/gorilla/websocket"
type Client struct {
ID uint32
Conn *websocket.Conn
}

View File

@@ -8,12 +8,44 @@ const (
EntityBullet EntityType = 3
)
type Entity struct {
ID uint32
Type EntityType
X float32
Y float32
Z float32
Yaw float32
type Entity interface {
GetID() uint32
GetType() EntityType
GetPosition() (float32, float32, float32)
SetPosition(float32, float32, float32)
GetYaw() float32
SetYaw(float32)
}
type BaseEntity struct {
ID uint32
Type EntityType
X, Y, Z float32
Yaw float32
}
func (e *BaseEntity) GetID() uint32 {
return e.ID
}
func (e *BaseEntity) GetType() EntityType {
return e.Type
}
func (e *BaseEntity) GetPosition() (float32, float32, float32) {
return e.X, e.Y, e.Z
}
func (e *BaseEntity) SetPosition(x, y, z float32) {
e.X = x
e.Y = y
e.Z = z
}
func (e *BaseEntity) GetYaw() float32 {
return e.Yaw
}
func (e *BaseEntity) SetYaw(yaw float32) {
e.Yaw = yaw
}

View File

@@ -1,9 +1,20 @@
package models
import "github.com/gorilla/websocket"
type Player struct {
Entity
BaseEntity
Name string
Conn *websocket.Conn
}
func NewPlayer(id uint32, name string) *Player {
return &Player{
BaseEntity: BaseEntity{
ID: id,
Type: EntityPlayer,
X: 0,
Y: 0,
Z: 0,
Yaw: 0,
},
Name: name,
}
}