Compare commits
4 Commits
61b7754c5c
...
0.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bb1e3bfd4 | ||
|
|
9cd779fbea | ||
|
|
3c989c33f8 | ||
|
|
1c60264d1d |
@@ -8,17 +8,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (h *Hub) readLoop(conn *websocket.Conn) {
|
func (h *Hub) readLoop(conn *websocket.Conn) {
|
||||||
handMessage := models.Message{Type: MSG_WELCOME}
|
var id uint32
|
||||||
_ = conn.WriteMessage(websocket.BinaryMessage, handMessage.Encode())
|
log.Println("client ws connected")
|
||||||
|
|
||||||
var player *models.Player
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if player != nil {
|
|
||||||
h.removePlayer(player.ID)
|
|
||||||
log.Println("Player left:", player.ID)
|
|
||||||
}
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
|
if id != 0 {
|
||||||
|
h.removeEntity(id)
|
||||||
|
log.Println("entity [player] removed:", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("client ws disconnected")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -36,20 +36,32 @@ func (h *Hub) readLoop(conn *websocket.Conn) {
|
|||||||
switch msg.Type {
|
switch msg.Type {
|
||||||
|
|
||||||
case MSG_WELCOME:
|
case MSG_WELCOME:
|
||||||
if player != nil {
|
reader := models.NewReader(msg.Payload)
|
||||||
continue
|
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:
|
case MSG_INPUT:
|
||||||
if player == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
reader := models.NewReader(msg.Payload)
|
reader := models.NewReader(msg.Payload)
|
||||||
|
id := reader.ReadU32()
|
||||||
x := reader.ReadF32()
|
x := reader.ReadF32()
|
||||||
y := 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
31
controllers/entities.go
Normal 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)
|
||||||
|
}
|
||||||
@@ -5,16 +5,20 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"server/models"
|
"server/models"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Hub struct {
|
type Hub struct {
|
||||||
Players map[uint32]*models.Player
|
Entities map[uint32]models.Entity
|
||||||
Mu sync.RWMutex
|
Clients map[uint32]*websocket.Conn
|
||||||
|
Mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHub() *Hub {
|
func NewHub() *Hub {
|
||||||
return &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
14
controllers/msg.go
Normal 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())
|
||||||
|
}
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -4,4 +4,5 @@ const (
|
|||||||
MSG_WELCOME = 0
|
MSG_WELCOME = 0
|
||||||
MSG_INPUT = 1
|
MSG_INPUT = 1
|
||||||
MSG_SNAPSHOT = 2
|
MSG_SNAPSHOT = 2
|
||||||
|
MSG_EVENT = 3
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,15 +12,16 @@ func (h *Hub) broadcastSnapshot() {
|
|||||||
defer h.Mu.RUnlock()
|
defer h.Mu.RUnlock()
|
||||||
|
|
||||||
w := models.Writer{}
|
w := models.Writer{}
|
||||||
w.WriteU16(uint16(len(h.Players)))
|
w.WriteU16(uint16(len(h.Entities)))
|
||||||
|
|
||||||
for _, p := range h.Players {
|
for _, e := range h.Entities {
|
||||||
w.WriteU32(p.ID)
|
w.WriteU32(e.GetID())
|
||||||
w.WriteU8(uint8(models.EntityPlayer))
|
w.WriteU8(uint8(e.GetType()))
|
||||||
w.WriteF32(p.X)
|
x, y, z := e.GetPosition()
|
||||||
w.WriteF32(p.Y)
|
w.WriteF32(x)
|
||||||
w.WriteF32(p.Z)
|
w.WriteF32(y)
|
||||||
w.WriteF32(p.Yaw)
|
w.WriteF32(z)
|
||||||
|
w.WriteF32(e.GetYaw())
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := models.Message{
|
msg := models.Message{
|
||||||
@@ -29,9 +30,9 @@ func (h *Hub) broadcastSnapshot() {
|
|||||||
Payload: w.Bytes(),
|
Payload: w.Bytes(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range h.Players {
|
for _, conn := range h.Clients {
|
||||||
if p.Conn != nil {
|
if conn != nil {
|
||||||
_ = p.Conn.WriteMessage(websocket.BinaryMessage, msg.Encode())
|
_ = conn.WriteMessage(websocket.BinaryMessage, msg.Encode())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
models/client.go
Normal file
8
models/client.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "github.com/gorilla/websocket"
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
ID uint32
|
||||||
|
Conn *websocket.Conn
|
||||||
|
}
|
||||||
@@ -8,12 +8,44 @@ const (
|
|||||||
EntityBullet EntityType = 3
|
EntityBullet EntityType = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
type Entity struct {
|
type Entity interface {
|
||||||
ID uint32
|
GetID() uint32
|
||||||
Type EntityType
|
GetType() EntityType
|
||||||
|
GetPosition() (float32, float32, float32)
|
||||||
X float32
|
SetPosition(float32, float32, float32)
|
||||||
Y float32
|
GetYaw() float32
|
||||||
Z float32
|
SetYaw(float32)
|
||||||
Yaw 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "github.com/gorilla/websocket"
|
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
Entity
|
BaseEntity
|
||||||
Name string
|
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user