You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
5.2 KiB
Go
183 lines
5.2 KiB
Go
package model
|
|
|
|
import "encoding/json"
|
|
|
|
// WSEnvelope is the wire format for all WebSocket messages (both directions).
|
|
type WSEnvelope struct {
|
|
Type string `json:"type"`
|
|
Payload json.RawMessage `json:"payload"`
|
|
}
|
|
|
|
// NewWSEnvelope creates an envelope by marshaling the payload to JSON.
|
|
// If marshaling fails, payload is set to "{}".
|
|
func NewWSEnvelope(msgType string, payload any) WSEnvelope {
|
|
raw, err := json.Marshal(payload)
|
|
if err != nil {
|
|
raw = []byte("{}")
|
|
}
|
|
return WSEnvelope{Type: msgType, Payload: raw}
|
|
}
|
|
|
|
// ClientMessage is a parsed inbound message from a WebSocket client,
|
|
// tagged with the hero ID of the sending connection.
|
|
type ClientMessage struct {
|
|
HeroID int64
|
|
Type string
|
|
Payload json.RawMessage
|
|
}
|
|
|
|
// --- Server -> Client payload types ---
|
|
|
|
// HeroMovePayload is sent at 2 Hz while the hero is walking.
|
|
type HeroMovePayload struct {
|
|
X float64 `json:"x"`
|
|
Y float64 `json:"y"`
|
|
TargetX float64 `json:"targetX"`
|
|
TargetY float64 `json:"targetY"`
|
|
Speed float64 `json:"speed"`
|
|
Heading float64 `json:"heading"` // radians
|
|
}
|
|
|
|
// PositionSyncPayload is sent every 10s as drift correction.
|
|
type PositionSyncPayload struct {
|
|
X float64 `json:"x"`
|
|
Y float64 `json:"y"`
|
|
WaypointIndex int `json:"waypointIndex"`
|
|
WaypointFraction float64 `json:"waypointFraction"`
|
|
State string `json:"state"`
|
|
}
|
|
|
|
// RouteAssignedPayload is sent when the hero starts walking a new road segment.
|
|
type RouteAssignedPayload struct {
|
|
RoadID int64 `json:"roadId"`
|
|
Waypoints []PointXY `json:"waypoints"`
|
|
DestinationTownID int64 `json:"destinationTownId"`
|
|
Speed float64 `json:"speed"`
|
|
}
|
|
|
|
// PointXY is a 2D coordinate used in route payloads.
|
|
type PointXY struct {
|
|
X float64 `json:"x"`
|
|
Y float64 `json:"y"`
|
|
}
|
|
|
|
// CombatStartPayload is sent when combat begins.
|
|
type CombatStartPayload struct {
|
|
Enemy CombatEnemyInfo `json:"enemy"`
|
|
}
|
|
|
|
// CombatEnemyInfo is the enemy snapshot sent to the client on combat_start.
|
|
type CombatEnemyInfo struct {
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
HP int `json:"hp"`
|
|
MaxHP int `json:"maxHp"`
|
|
Attack int `json:"attack"`
|
|
Defense int `json:"defense"`
|
|
Speed float64 `json:"speed"`
|
|
IsElite bool `json:"isElite"`
|
|
}
|
|
|
|
// AttackPayload is sent on each swing during combat.
|
|
type AttackPayload struct {
|
|
Source string `json:"source"` // "hero" or "enemy"
|
|
Damage int `json:"damage"`
|
|
IsCrit bool `json:"isCrit,omitempty"`
|
|
HeroHP int `json:"heroHp"`
|
|
EnemyHP int `json:"enemyHp"`
|
|
DebuffApplied string `json:"debuffApplied,omitempty"`
|
|
}
|
|
|
|
// CombatEndPayload is sent when the hero wins a fight.
|
|
type CombatEndPayload struct {
|
|
XPGained int64 `json:"xpGained"`
|
|
GoldGained int64 `json:"goldGained"`
|
|
Loot []LootItem `json:"loot,omitempty"`
|
|
LeveledUp bool `json:"leveledUp"`
|
|
NewLevel int `json:"newLevel,omitempty"`
|
|
}
|
|
|
|
// LootItem describes a single piece of loot in the combat_end payload.
|
|
type LootItem struct {
|
|
ItemType string `json:"itemType"`
|
|
Name string `json:"name"`
|
|
Rarity string `json:"rarity"`
|
|
}
|
|
|
|
// HeroDiedPayload is sent when the hero's HP reaches 0.
|
|
type HeroDiedPayload struct {
|
|
KilledBy string `json:"killedBy"`
|
|
}
|
|
|
|
// HeroRevivedPayload is sent after a revive.
|
|
type HeroRevivedPayload struct {
|
|
HP int `json:"hp"`
|
|
}
|
|
|
|
// TownNPCInfo describes an NPC in a town (town_enter payload).
|
|
type TownNPCInfo struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
// TownEnterPayload is sent when a hero arrives at a town.
|
|
type TownEnterPayload struct {
|
|
TownID int64 `json:"townId"`
|
|
TownName string `json:"townName"`
|
|
Biome string `json:"biome"`
|
|
NPCs []TownNPCInfo `json:"npcs"`
|
|
RestDurationMs int64 `json:"restDurationMs"`
|
|
}
|
|
|
|
// TownNPCVisitPayload is sent when the hero approaches an NPC (quest/shop/healer) during a town stay.
|
|
type TownNPCVisitPayload struct {
|
|
NPCID int64 `json:"npcId"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
TownID int64 `json:"townId"`
|
|
}
|
|
|
|
// TownExitPayload is sent when the hero leaves a town.
|
|
type TownExitPayload struct{}
|
|
|
|
// LevelUpPayload is sent on level-up.
|
|
type LevelUpPayload struct {
|
|
NewLevel int `json:"newLevel"`
|
|
}
|
|
|
|
// BuffAppliedPayload is sent when a buff is activated.
|
|
type BuffAppliedPayload struct {
|
|
BuffType string `json:"buffType"`
|
|
Duration float64 `json:"duration"` // seconds
|
|
Magnitude float64 `json:"magnitude"`
|
|
}
|
|
|
|
// ErrorPayload is sent when a client command fails validation.
|
|
type ErrorPayload struct {
|
|
Code string `json:"code"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// --- Client -> Server payload types ---
|
|
|
|
// ActivateBuffPayload is the payload for the activate_buff command.
|
|
type ActivateBuffPayload struct {
|
|
BuffType string `json:"buffType"`
|
|
}
|
|
|
|
// AcceptQuestPayload is the payload for the accept_quest command.
|
|
type AcceptQuestPayload struct {
|
|
QuestID int64 `json:"questId"`
|
|
}
|
|
|
|
// ClaimQuestPayload is the payload for the claim_quest command.
|
|
type ClaimQuestPayload struct {
|
|
QuestID int64 `json:"questId"`
|
|
}
|
|
|
|
// NPCInteractPayload is the payload for the npc_interact command.
|
|
type NPCInteractPayload struct {
|
|
NPCID int64 `json:"npcId"`
|
|
}
|