Fix segfaults by avoiding models and animations for now

This commit is contained in:
2025-04-16 10:47:46 +02:00
parent 220a451475
commit 5bf962a18d
5 changed files with 370 additions and 74 deletions

View File

@ -170,8 +170,18 @@ func (g *Game) DrawPlayer(player *types.Player, model rl.Model) {
player.Lock()
defer player.Unlock()
// Check for invalid model
if model.Meshes == nil || model.Meshes.VertexCount <= 0 {
// Don't try to draw invalid models
return
}
grid := GetMapGrid()
modelIndex := int(player.ID) % len(g.Models)
if modelIndex < 0 || modelIndex >= len(g.Models) {
// Prevent out of bounds access
modelIndex = 0
}
modelAsset := g.Models[modelIndex]
const defaultHeight = 8.0 // Default height above tile, fine tune per model in types.ModelAsset
@ -185,16 +195,25 @@ func (g *Game) DrawPlayer(player *types.Player, model rl.Model) {
if modelAsset.Animations.Idle != nil || modelAsset.Animations.Walk != nil {
if player.IsMoving && len(modelAsset.Animations.Walk) > 0 {
anim := modelAsset.Animations.Walk[0] // Use first walk animation
player.AnimationFrame = player.AnimationFrame % anim.FrameCount
rl.UpdateModelAnimation(model, anim, player.AnimationFrame)
if anim.FrameCount > 0 {
player.AnimationFrame = player.AnimationFrame % anim.FrameCount
rl.UpdateModelAnimation(model, anim, player.AnimationFrame)
}
} else if len(modelAsset.Animations.Idle) > 0 {
anim := modelAsset.Animations.Idle[0] // Use first idle animation
player.AnimationFrame = player.AnimationFrame % anim.FrameCount
rl.UpdateModelAnimation(model, anim, player.AnimationFrame)
if anim.FrameCount > 0 {
player.AnimationFrame = player.AnimationFrame % anim.FrameCount
rl.UpdateModelAnimation(model, anim, player.AnimationFrame)
}
}
}
rl.DrawModel(model, playerPos, 16, rl.White)
// Use placeholder color if it's set, otherwise use white
var drawColor rl.Color = rl.White
if player.PlaceholderColor.A > 0 {
drawColor = player.PlaceholderColor
}
rl.DrawModel(model, playerPos, 16, drawColor)
// Draw floating messages and path indicators
if player.FloatingMessage != nil {
@ -228,20 +247,43 @@ func (g *Game) DrawPlayer(player *types.Player, model rl.Model) {
func (g *Game) Render() {
rl.BeginDrawing()
defer func() {
// This defer will catch any panics that might occur during rendering
// and ensure EndDrawing gets called to maintain proper graphics state
if r := recover(); r != nil {
rl.TraceLog(rl.LogError, "Panic during rendering: %v", r)
}
rl.EndDrawing()
}()
rl.ClearBackground(rl.RayWhite)
if !g.isLoggedIn {
g.loginScreen.Draw()
rl.EndDrawing()
return
}
rl.BeginMode3D(g.Camera)
g.DrawMap()
g.DrawPlayer(g.Player, g.Player.Model)
// Draw player only if valid
if g.Player != nil && g.Player.Model.Meshes != nil {
g.DrawPlayer(g.Player, g.Player.Model)
}
// Draw other players with defensive checks
for _, other := range g.OtherPlayers {
if other == nil {
continue
}
// Make sure model is assigned
if other.Model.Meshes == nil {
g.AssignModelToPlayer(other)
// Skip this frame if assignment failed
if other.Model.Meshes == nil {
continue
}
}
g.DrawPlayer(other, other.Model)
}
@ -268,12 +310,14 @@ func (g *Game) Render() {
rl.DrawText(text, int32(pos.X)-textWidth/2, int32(pos.Y), 20, rl.Yellow)
}
if g.Player.FloatingMessage != nil {
if g.Player != nil && g.Player.FloatingMessage != nil {
drawFloatingMessage(g.Player.FloatingMessage)
}
for _, other := range g.OtherPlayers {
drawFloatingMessage(other.FloatingMessage)
if other != nil && other.FloatingMessage != nil {
drawFloatingMessage(other.FloatingMessage)
}
}
// Draw menu if open
@ -282,12 +326,11 @@ func (g *Game) Render() {
}
// Only draw chat if menu is not open
if !g.MenuOpen {
if !g.MenuOpen && g.Chat != nil {
g.Chat.Draw(int32(rl.GetScreenWidth()), int32(rl.GetScreenHeight()))
}
rl.DrawFPS(10, 10)
rl.EndDrawing()
}
func (g *Game) Cleanup() {
@ -392,12 +435,33 @@ func (g *Game) HandleServerMessages(messages []*pb.ChatMessage) {
}
func (g *Game) AssignModelToPlayer(player *types.Player) {
if player == nil {
return
}
// Defensive check for empty models array
if len(g.Models) == 0 {
rl.TraceLog(rl.LogWarning, "No models available to assign to player")
return
}
modelIndex := int(player.ID) % len(g.Models)
if modelIndex < 0 || modelIndex >= len(g.Models) {
// Prevent out of bounds access
modelIndex = 0
}
modelAsset := g.Models[modelIndex]
// Just use the original model - don't try to copy it
// Validate model before assigning
if modelAsset.Model.Meshes == nil {
rl.TraceLog(rl.LogWarning, "Trying to assign invalid model to player %d", player.ID)
return
}
player.Model = modelAsset.Model
player.Texture = modelAsset.Texture
player.PlaceholderColor = modelAsset.PlaceholderColor
}
func (g *Game) QuitChan() <-chan struct{} {