new files

This commit is contained in:
Smile Rex
2026-01-14 11:34:03 +03:00
parent 7acd741749
commit d3a19d5066
4 changed files with 105 additions and 183 deletions

76
controllers/hub.go Normal file
View File

@@ -0,0 +1,76 @@
package controllers
import (
"bytes"
"encoding/binary"
"log"
"net/http"
"server/models"
"github.com/gorilla/websocket"
)
type Hub struct {
Players map[uint32]*models.Player
ServerBuffer []byte
}
func NewHub() *Hub {
return &Hub{
Players: make(map[uint32]*models.Player),
}
}
func (h *Hub) readLoop(conn *websocket.Conn) {
p := &models.Player{
Conn: conn,
InputX: 0,
InputZ: 0,
}
log.Println("Player connected:", p.ID)
h.Players[p.ID] = p
defer func() {
delete(h.Players, p.ID)
p.Conn.Close()
log.Println("Player disconnected:", p.ID)
}()
for {
_, data, err := p.Conn.ReadMessage()
if err != nil {
return
}
if len(data) < 8 {
continue
}
buf := bytes.NewReader(data)
binary.Read(buf, binary.LittleEndian, &p.InputX)
binary.Read(buf, binary.LittleEndian, &p.InputZ)
}
}
func (h *Hub) StartWS(w http.ResponseWriter, r *http.Request) {
upgrader := websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
for {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
continue
}
go h.readLoop(conn)
}
}
func (h *Hub) Start() {
http.HandleFunc("/ws", h.StartWS)
log.Fatal(http.ListenAndServe(":8080", nil))
}

187
main.go
View File

@@ -1,191 +1,12 @@
package main
import (
"bytes"
"encoding/binary"
"log"
"math/rand"
"net/http"
"sync"
"time"
"github.com/gorilla/websocket"
)
const (
PacketHandshake uint8 = 0
PacketWorld uint8 = 1
TickRate = 30
Speed = 5.0
SpawnMinX = -5.0
SpawnMaxX = 5.0
SpawnMinZ = -5.0
SpawnMaxZ = 5.0
SpawnRadius = 1.5
)
type Player struct {
ID uint32
X float32
Y float32
Z float32
InputX float32
InputZ float32
Conn *websocket.Conn
}
var (
upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
players = make(map[uint32]*Player)
playersMu sync.Mutex
nextID uint32 = 1
"server/controllers"
)
func main() {
rand.Seed(time.Now().UnixNano())
http.HandleFunc("/ws", handleWS)
go gameLoop()
log.Println("Server running on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handleWS(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
playersMu.Lock()
id := nextID
nextID++
x, z := randomSpawnPosition()
player := &Player{
ID: id,
X: x,
Y: 0,
Z: z,
Conn: conn,
}
players[id] = player
playersMu.Unlock()
{
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, PacketHandshake)
binary.Write(buf, binary.LittleEndian, id)
conn.WriteMessage(websocket.BinaryMessage, buf.Bytes())
}
log.Println("Player connected:", id, "spawn at", x, z)
go readLoop(player)
}
func randomSpawnPosition() (float32, float32) {
for i := 0; i < 20; i++ {
x := rand.Float32()*(SpawnMaxX-SpawnMinX) + SpawnMinX
z := rand.Float32()*(SpawnMaxZ-SpawnMinZ) + SpawnMinZ
if isSpawnFree(x, z) {
return x, z
}
}
// fallback
return 0, 0
}
func isSpawnFree(x, z float32) bool {
for _, p := range players {
dx := p.X - x
dz := p.Z - z
if dx*dx+dz*dz < SpawnRadius*SpawnRadius {
return false
}
}
return true
}
func readLoop(p *Player) {
defer func() {
playersMu.Lock()
delete(players, p.ID)
playersMu.Unlock()
p.Conn.Close()
log.Println("Player disconnected:", p.ID)
}()
for {
_, data, err := p.Conn.ReadMessage()
if err != nil {
return
}
if len(data) < 8 {
continue
}
buf := bytes.NewReader(data)
binary.Read(buf, binary.LittleEndian, &p.InputX)
binary.Read(buf, binary.LittleEndian, &p.InputZ)
}
}
func gameLoop() {
ticker := time.NewTicker(time.Second / TickRate)
defer ticker.Stop()
dt := float32(1.0 / TickRate)
for range ticker.C {
update(dt)
broadcast()
}
}
func update(dt float32) {
playersMu.Lock()
defer playersMu.Unlock()
for _, p := range players {
p.X += p.InputX * Speed * dt
p.Z += p.InputZ * Speed * dt
}
}
func broadcast() {
playersMu.Lock()
defer playersMu.Unlock()
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, PacketWorld)
binary.Write(buf, binary.LittleEndian, uint16(len(players)))
for _, p := range players {
binary.Write(buf, binary.LittleEndian, p.ID)
binary.Write(buf, binary.LittleEndian, p.X)
binary.Write(buf, binary.LittleEndian, p.Y)
binary.Write(buf, binary.LittleEndian, p.Z)
}
data := buf.Bytes()
for _, p := range players {
p.Conn.WriteMessage(websocket.BinaryMessage, data)
}
hub := controllers.NewHub()
log.Println("Server listening websocket on :8080")
hub.Start()
}

6
models/message.go Normal file
View File

@@ -0,0 +1,6 @@
package models
type Message struct {
Type int8
Payload interface{}
}

19
models/player.go Normal file
View File

@@ -0,0 +1,19 @@
package models
import "github.com/gorilla/websocket"
type Player struct {
ID uint32
X float32
Y float32
Z float32
InputX float32
InputZ float32
Name string
PhotoURL string
Conn *websocket.Conn
}