Fix chat and other players not showing up

This commit is contained in:
bdnugget 2025-04-16 11:13:52 +02:00
parent 5bf962a18d
commit 555b8118f2
6 changed files with 80 additions and 33 deletions

View File

@ -2,20 +2,11 @@ package main
import "time"
// Game world constants
const (
MapWidth = 50
MapHeight = 50
TileSize = 32
TileHeight = 2.0
TickRate = 600 * time.Millisecond // Server tick rate (600ms)
serverAddr = "localhost:6969"
// RuneScape-style tick rate (600ms)
ServerTickRate = 600 * time.Millisecond
// Client might run at a higher tick rate for smooth rendering
ClientTickRate = 50 * time.Millisecond
// Maximum number of ticks we can get behind before forcing a resync
MaxTickDesync = 5
// Server-related constants
ServerTickRate = 600 * time.Millisecond // RuneScape-style tick rate
ClientTickRate = 50 * time.Millisecond // Client runs at higher rate for smooth rendering
MaxTickDesync = 5 // Max ticks behind before forcing resync
DefaultPort = "6969" // Default server port
)

View File

@ -2,6 +2,7 @@ package game
import (
"fmt"
"log"
"sync"
"time"
@ -54,6 +55,12 @@ func (c *Chat) HandleServerMessages(messages []*pb.ChatMessage) {
c.mutex.Lock()
defer c.mutex.Unlock()
if len(messages) == 0 {
return
}
log.Printf("Processing %d chat messages", len(messages))
// Convert protobuf messages to our local type
for _, msg := range messages {
localMsg := types.ChatMessage{
@ -69,6 +76,7 @@ func (c *Chat) HandleServerMessages(messages []*pb.ChatMessage) {
c.messages = c.messages[1:]
}
c.messages = append(c.messages, localMsg)
log.Printf("Added chat message from %s: %s", msg.Username, msg.Content)
// Scroll to latest message if it's not already visible
visibleMessages := int((chatHeight - inputHeight) / messageHeight)
@ -92,6 +100,9 @@ func (c *Chat) HandleServerMessages(messages []*pb.ChatMessage) {
ExpireTime: time.Now().Add(6 * time.Second),
}
otherPlayer.Unlock()
log.Printf("Added floating message to other player %d", msg.PlayerId)
} else {
log.Printf("Could not find other player %d to add floating message", msg.PlayerId)
}
}
}

View File

@ -24,6 +24,7 @@ type Game struct {
loginScreen *LoginScreen
isLoggedIn bool
cleanupOnce sync.Once
frameCounter int // For periodic logging
}
func New() *Game {
@ -129,7 +130,28 @@ func (g *Game) Update(deltaTime float32) {
g.Player.MoveTowards(g.Player.TargetPath[0], deltaTime, GetMapGrid())
}
// Periodically log information about other players
g.frameCounter++
if g.frameCounter%300 == 0 {
rl.TraceLog(rl.LogInfo, "There are %d other players", len(g.OtherPlayers))
for id, other := range g.OtherPlayers {
rl.TraceLog(rl.LogInfo, "Other player ID: %d, Position: (%f, %f, %f), Has model: %v",
id, other.PosActual.X, other.PosActual.Y, other.PosActual.Z, other.Model.Meshes != nil)
}
}
// Process other players
for _, other := range g.OtherPlayers {
if other == nil {
continue
}
// Make sure other players have models assigned
if other.Model.Meshes == nil {
g.AssignModelToPlayer(other)
}
// Update other player movement
if len(other.TargetPath) > 0 {
other.MoveTowards(other.TargetPath[0], deltaTime, GetMapGrid())
}
@ -167,8 +189,8 @@ func (g *Game) DrawMap() {
}
func (g *Game) DrawPlayer(player *types.Player, model rl.Model) {
player.Lock()
defer player.Unlock()
// No need for lock in rendering, we'll use a "take snapshot" approach
// This avoids potential deadlocks and makes the rendering more consistent
// Check for invalid model
if model.Meshes == nil || model.Meshes.VertexCount <= 0 {
@ -196,14 +218,14 @@ func (g *Game) DrawPlayer(player *types.Player, model rl.Model) {
if player.IsMoving && len(modelAsset.Animations.Walk) > 0 {
anim := modelAsset.Animations.Walk[0] // Use first walk animation
if anim.FrameCount > 0 {
player.AnimationFrame = player.AnimationFrame % anim.FrameCount
rl.UpdateModelAnimation(model, anim, player.AnimationFrame)
currentFrame := player.AnimationFrame % anim.FrameCount
rl.UpdateModelAnimation(model, anim, currentFrame)
}
} else if len(modelAsset.Animations.Idle) > 0 {
anim := modelAsset.Animations.Idle[0] // Use first idle animation
if anim.FrameCount > 0 {
player.AnimationFrame = player.AnimationFrame % anim.FrameCount
rl.UpdateModelAnimation(model, anim, player.AnimationFrame)
currentFrame := player.AnimationFrame % anim.FrameCount
rl.UpdateModelAnimation(model, anim, currentFrame)
}
}
}
@ -445,12 +467,15 @@ func (g *Game) AssignModelToPlayer(player *types.Player) {
return
}
modelIndex := int(player.ID) % len(g.Models)
// Make sure model index is positive for consistent player appearances
// Use abs value of ID to ensure consistent appearance for negative IDs
modelIndex := abs(int(player.ID)) % len(g.Models)
if modelIndex < 0 || modelIndex >= len(g.Models) {
// Prevent out of bounds access
modelIndex = 0
}
rl.TraceLog(rl.LogInfo, "Assigning model %d to player %d", modelIndex, player.ID)
modelAsset := g.Models[modelIndex]
// Validate model before assigning

View File

@ -51,7 +51,7 @@ func main() {
}
// Initialize window with error handling
rl.SetConfigFlags(rl.FlagMsaa4xHint) // Enable MSAA for smoother rendering
rl.SetConfigFlags(rl.FlagMsaa4xHint | rl.FlagWindowResizable) // Enable MSAA and make window resizable
rl.InitWindow(1024, 768, "GoonScape")
rl.SetExitKey(0)

View File

@ -18,10 +18,11 @@ import (
const protoVersion = 1
var serverAddr = "boner.be:6969"
var serverAddr = "boner.be:6969" // Default server address
func SetServerAddr(addr string) {
serverAddr = addr
log.Printf("Server address set to: %s", serverAddr)
}
func ConnectToServer(username, password string, isRegistering bool) (net.Conn, int32, error) {
@ -175,22 +176,33 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
lengthBuf := make([]byte, 4)
if _, err := io.ReadFull(reader, lengthBuf); err != nil {
if err != io.EOF {
log.Printf("Network read error: %v", err)
errChan <- fmt.Errorf("failed to read message length: %v", err)
} else {
log.Printf("Connection closed by server")
}
return
}
messageLength := binary.BigEndian.Uint32(lengthBuf)
// Sanity check message size to prevent potential memory issues
if messageLength > 1024*1024 { // 1MB max message size
log.Printf("Message size too large: %d bytes", messageLength)
errChan <- fmt.Errorf("message size too large: %d bytes", messageLength)
return
}
messageBuf := make([]byte, messageLength)
if _, err := io.ReadFull(reader, messageBuf); err != nil {
log.Printf("Failed to read message body: %v", err)
errChan <- fmt.Errorf("failed to read message body: %v", err)
return
}
var serverMessage pb.ServerMessage
if err := proto.Unmarshal(messageBuf, &serverMessage); err != nil {
log.Printf("Failed to unmarshal server message: %v", err)
continue
continue // Skip this message but don't quit
}
player.Lock()
@ -207,7 +219,11 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
}
player.Unlock()
// Process player states
validPlayerIds := make(map[int32]bool)
for _, state := range serverMessage.Players {
validPlayerIds[state.PlayerId] = true
if state.PlayerId == playerID {
player.Lock()
// Update initial position if not set
@ -223,21 +239,26 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
continue
}
// Update or create other players
if otherPlayer, exists := otherPlayers[state.PlayerId]; exists {
otherPlayer.UpdatePosition(state, types.ServerTickRate)
} else {
log.Printf("Creating new player with ID: %d", state.PlayerId)
otherPlayers[state.PlayerId] = types.NewPlayer(state)
}
}
// Remove players that are no longer in the server state
// Remove players no longer in the server state
for id := range otherPlayers {
if id != playerID {
if id != playerID && !validPlayerIds[id] {
log.Printf("Removing player with ID: %d", id)
delete(otherPlayers, id)
}
}
// Handle chat messages
if handler, ok := player.UserData.(types.ChatMessageHandler); ok && len(serverMessage.ChatMessages) > 0 {
log.Printf("Received %d chat messages from server", len(serverMessage.ChatMessages))
handler.HandleServerMessages(serverMessage.ChatMessages)
}
}

View File

@ -9,7 +9,7 @@ import (
)
type Player struct {
sync.RWMutex
sync.RWMutex // Keep this for network operations
Model rl.Model
Texture rl.Texture2D
PosActual rl.Vector3
@ -31,9 +31,7 @@ type Player struct {
}
func (p *Player) MoveTowards(target Tile, deltaTime float32, mapGrid [][]Tile) {
p.Lock()
defer p.Unlock()
// No need for lock here as this is called from a single thread (game loop)
targetPos := rl.Vector3{
X: float32(target.X * TileSize),
Y: mapGrid[target.X][target.Y].Height * TileHeight,
@ -53,7 +51,7 @@ func (p *Player) MoveTowards(target Tile, deltaTime float32, mapGrid [][]Tile) {
oldFrame := p.AnimationFrame
p.AnimationFrame += int32(deltaTime * 60)
rl.TraceLog(rl.LogInfo, "Walk frame update: %d -> %d (delta: %f)",
rl.TraceLog(rl.LogDebug, "Walk frame update: %d -> %d (delta: %f)",
oldFrame, p.AnimationFrame, deltaTime)
} else {
wasMoving := p.IsMoving
@ -65,7 +63,7 @@ func (p *Player) MoveTowards(target Tile, deltaTime float32, mapGrid [][]Tile) {
oldFrame := p.AnimationFrame
p.AnimationFrame += int32(deltaTime * 60)
rl.TraceLog(rl.LogInfo, "Idle frame update: %d -> %d (delta: %f)",
rl.TraceLog(rl.LogDebug, "Idle frame update: %d -> %d (delta: %f)",
oldFrame, p.AnimationFrame, deltaTime)
}
@ -116,6 +114,7 @@ func (p *Player) UpdatePosition(state *pb.PlayerState, tickRate time.Duration) {
}
func (p *Player) ForceResync(state *pb.PlayerState) {
// Keep this lock since it's called from the network goroutine
p.Lock()
defer p.Unlock()