mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-04 17:27:16 -05:00
* saving of player should be done on the server. That's also where the loading happens. * refactor nearly everything, but this time it looks not that bad... * MAke Linter happy * Typo... uuups
This commit is contained in:
parent
fb8e25ebdb
commit
40cc421f51
@ -7,14 +7,16 @@ import (
|
||||
|
||||
// HeroState stores the state of the player
|
||||
type HeroState struct {
|
||||
HeroName string `json:"heroName"`
|
||||
HeroType d2enum.Hero `json:"heroType"`
|
||||
HeroLevel int `json:"heroLevel"`
|
||||
Act int `json:"act"`
|
||||
FilePath string `json:"-"`
|
||||
Equipment d2inventory.CharacterEquipment `json:"equipment"`
|
||||
Stats *HeroStatsState `json:"stats"`
|
||||
Skills map[int]*HeroSkill `json:"skills"`
|
||||
X float64 `json:"x"`
|
||||
Y float64 `json:"y"`
|
||||
HeroName string `json:"heroName"`
|
||||
HeroType d2enum.Hero `json:"heroType"`
|
||||
HeroLevel int `json:"heroLevel"`
|
||||
Act int `json:"act"`
|
||||
FilePath string `json:"-"`
|
||||
Equipment d2inventory.CharacterEquipment `json:"equipment"`
|
||||
Stats *HeroStatsState `json:"stats"`
|
||||
Skills map[int]*HeroSkill `json:"skills"`
|
||||
X float64 `json:"x"`
|
||||
Y float64 `json:"y"`
|
||||
LeftSkill int `json:"leftSkill"`
|
||||
RightSkill int `json:"rightSkill"`
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ func NewAnimatedEntity(x, y int, animation d2interface.Animation) *AnimatedEntit
|
||||
|
||||
// NewPlayer creates a new player entity and returns a pointer to it.
|
||||
func (f *MapEntityFactory) NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
|
||||
stats *d2hero.HeroStatsState, skills map[int]*d2hero.HeroSkill, equipment *d2inventory.CharacterEquipment) *Player {
|
||||
stats *d2hero.HeroStatsState, skills map[int]*d2hero.HeroSkill, equipment *d2inventory.CharacterEquipment,
|
||||
leftSkill, rightSkill int) *Player {
|
||||
layerEquipment := &[d2enum.CompositeTypeMax]string{
|
||||
d2enum.CompositeTypeHead: equipment.Head.GetArmorClass(),
|
||||
d2enum.CompositeTypeTorso: equipment.Torso.GetArmorClass(),
|
||||
@ -89,16 +90,14 @@ func (f *MapEntityFactory) NewPlayer(id, name string, x, y, direction int, heroT
|
||||
statsState := f.HeroStateFactory.CreateHeroStatsState(heroType, defaultCharStats)
|
||||
heroState, _ := f.CreateHeroState(name, heroType, statsState)
|
||||
|
||||
attackSkillID := 0
|
||||
result := &Player{
|
||||
mapEntity: newMapEntity(x, y),
|
||||
composite: composite,
|
||||
Equipment: equipment,
|
||||
Stats: heroState.Stats,
|
||||
Skills: heroState.Skills,
|
||||
// https://github.com/OpenDiablo2/OpenDiablo2/issues/799
|
||||
LeftSkill: heroState.Skills[attackSkillID],
|
||||
RightSkill: heroState.Skills[attackSkillID],
|
||||
mapEntity: newMapEntity(x, y),
|
||||
composite: composite,
|
||||
Equipment: equipment,
|
||||
Stats: heroState.Stats,
|
||||
Skills: heroState.Skills,
|
||||
LeftSkill: heroState.Skills[leftSkill],
|
||||
RightSkill: heroState.Skills[rightSkill],
|
||||
name: name,
|
||||
Class: heroType,
|
||||
//nameLabel: d2ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteStatic),
|
||||
@ -108,7 +107,6 @@ func (f *MapEntityFactory) NewPlayer(id, name string, x, y, direction int, heroT
|
||||
}
|
||||
|
||||
result.mapEntity.uuid = id
|
||||
// https://github.com/OpenDiablo2/OpenDiablo2/issues/799
|
||||
result.SetSpeed(baseWalkSpeed)
|
||||
result.mapEntity.directioner = result.rotate
|
||||
err = composite.SetMode(d2enum.PlayerAnimationModeTownNeutral, equipment.RightHand.GetWeaponClass())
|
||||
|
@ -353,6 +353,8 @@ func (v *CharacterSelect) updateCharacterBoxes() {
|
||||
v.gameStates[idx].Stats,
|
||||
v.gameStates[idx].Skills,
|
||||
&equipment,
|
||||
v.gameStates[idx].LeftSkill,
|
||||
v.gameStates[idx].RightSkill,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -186,6 +186,10 @@ func (v *Game) OnUnload() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := v.OnPlayerSave(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := v.gameClient.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -309,14 +313,26 @@ func (v *Game) OnPlayerMove(targetX, targetY float64) {
|
||||
worldPosition := v.localPlayer.Position.World()
|
||||
|
||||
playerID, worldX, worldY := v.gameClient.PlayerID, worldPosition.X(), worldPosition.Y()
|
||||
createPlayerPacket := d2netpacket.CreateMovePlayerPacket(playerID, worldX, worldY, targetX, targetY)
|
||||
err := v.gameClient.SendPacketToServer(createPlayerPacket)
|
||||
createMovePlayerPacket := d2netpacket.CreateMovePlayerPacket(playerID, worldX, worldY, targetX, targetY)
|
||||
err := v.gameClient.SendPacketToServer(createMovePlayerPacket)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf(moveErrStr, v.gameClient.PlayerID, targetX, targetY)
|
||||
}
|
||||
}
|
||||
|
||||
// OnPlayerSave instructs the server to save our player data
|
||||
func (v *Game) OnPlayerSave() error {
|
||||
playerState := v.gameClient.Players[v.gameClient.PlayerID]
|
||||
err := v.gameClient.SendPacketToServer(d2netpacket.CreateSavePlayerPacket(playerState))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnPlayerCast sends the casting skill action to the server
|
||||
func (v *Game) OnPlayerCast(skillID int, targetX, targetY float64) {
|
||||
err := v.gameClient.SendPacketToServer(d2netpacket.CreateCastPacket(v.gameClient.PlayerID, skillID, targetX, targetY))
|
||||
|
@ -801,7 +801,6 @@ func (g *GameControls) Load() {
|
||||
log.Print(err)
|
||||
}
|
||||
|
||||
// https://github.com/OpenDiablo2/OpenDiablo2/issues/799
|
||||
genericSkillsSprite, err := g.ui.NewSprite(d2resource.GenericSkills, d2resource.PaletteSky)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
|
@ -207,7 +207,7 @@ func (g *GameClient) handleAddPlayerPacket(packet d2netpacket.NetPacket) error {
|
||||
d2hero.HydrateSkills(player.Skills, g.asset)
|
||||
|
||||
newPlayer := g.MapEngine.NewPlayer(player.ID, player.Name, player.X, player.Y, 0,
|
||||
player.HeroType, player.Stats, player.Skills, &player.Equipment)
|
||||
player.HeroType, player.Stats, player.Skills, &player.Equipment, player.LeftSkill, player.RightSkill)
|
||||
|
||||
g.Players[newPlayer.ID()] = newPlayer
|
||||
g.MapEngine.AddEntity(newPlayer)
|
||||
|
@ -30,6 +30,7 @@ const (
|
||||
ServerClosed // Sent by the local host when it has closed the server
|
||||
CastSkill // Sent by client or server, indicates entity casting skill
|
||||
SpawnItem // Sent by server
|
||||
SavePlayer // Sent by the client, saves the player
|
||||
|
||||
UnknownPacketType = 666
|
||||
)
|
||||
@ -47,6 +48,7 @@ func (n NetPacketType) String() string {
|
||||
ServerClosed: "ServerClosed",
|
||||
CastSkill: "CastSkill",
|
||||
SpawnItem: "SpawnItem",
|
||||
SavePlayer: "SavePlayer",
|
||||
}
|
||||
|
||||
return strings[n]
|
||||
|
@ -14,29 +14,34 @@ import (
|
||||
// It is sent by the server to create the entity for a newly connected
|
||||
// player on a client.
|
||||
type AddPlayerPacket struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
X int `json:"x"`
|
||||
Y int `json:"y"`
|
||||
HeroType d2enum.Hero `json:"hero"`
|
||||
Equipment d2inventory.CharacterEquipment `json:"equipment"`
|
||||
Stats *d2hero.HeroStatsState `json:"heroStats"`
|
||||
Skills map[int]*d2hero.HeroSkill `json:"heroSkills"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
X int `json:"x"`
|
||||
Y int `json:"y"`
|
||||
HeroType d2enum.Hero `json:"hero"`
|
||||
Equipment d2inventory.CharacterEquipment `json:"equipment"`
|
||||
Stats *d2hero.HeroStatsState `json:"heroStats"`
|
||||
Skills map[int]*d2hero.HeroSkill `json:"heroSkills"`
|
||||
LeftSkill int `json:"leftSkill"`
|
||||
RightSkill int `json:"rightSkill"`
|
||||
}
|
||||
|
||||
// CreateAddPlayerPacket returns a NetPacket which declares an
|
||||
// AddPlayerPacket with the data in given parameters.
|
||||
func CreateAddPlayerPacket(id, name string, x, y int, heroType d2enum.Hero,
|
||||
stats *d2hero.HeroStatsState, skills map[int]*d2hero.HeroSkill, equipment d2inventory.CharacterEquipment) NetPacket {
|
||||
stats *d2hero.HeroStatsState, skills map[int]*d2hero.HeroSkill, equipment d2inventory.CharacterEquipment,
|
||||
leftSkill, rightSkill int) NetPacket {
|
||||
addPlayerPacket := AddPlayerPacket{
|
||||
ID: id,
|
||||
Name: name,
|
||||
X: x,
|
||||
Y: y,
|
||||
HeroType: heroType,
|
||||
Equipment: equipment,
|
||||
Stats: stats,
|
||||
Skills: skills,
|
||||
ID: id,
|
||||
Name: name,
|
||||
X: x,
|
||||
Y: y,
|
||||
HeroType: heroType,
|
||||
Equipment: equipment,
|
||||
Stats: stats,
|
||||
Skills: skills,
|
||||
LeftSkill: leftSkill,
|
||||
RightSkill: rightSkill,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(addPlayerPacket)
|
||||
|
44
d2networking/d2netpacket/packet_save_player.go
Normal file
44
d2networking/d2netpacket/packet_save_player.go
Normal file
@ -0,0 +1,44 @@
|
||||
package d2netpacket
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
|
||||
)
|
||||
|
||||
// SavePlayerPacket has the actual selected left and right skill
|
||||
// the Server has to check if these skills are actually allowed for the Player
|
||||
type SavePlayerPacket struct {
|
||||
LeftSkill int `json:"leftSkill"`
|
||||
RightSkill int `json:"rightSkill"`
|
||||
}
|
||||
|
||||
// CreateSavePlayerPacket sends a packet which instructs the server to save the Player
|
||||
func CreateSavePlayerPacket(playerState *d2mapentity.Player) NetPacket {
|
||||
savePlayerData := SavePlayerPacket{
|
||||
LeftSkill: playerState.LeftSkill.ID,
|
||||
RightSkill: playerState.RightSkill.ID,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(savePlayerData)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
|
||||
return NetPacket{
|
||||
PacketType: d2netpackettype.SavePlayer,
|
||||
PacketData: b,
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalSavePlayer unmarshalls the given data to a SavePlayerPacket struct
|
||||
func UnmarshalSavePlayer(packet []byte) (SavePlayerPacket, error) {
|
||||
var p SavePlayerPacket
|
||||
if err := json.Unmarshal(packet, &p); err != nil {
|
||||
return p, err
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
@ -50,6 +50,7 @@ type GameServer struct {
|
||||
seed int64
|
||||
maxConnections int
|
||||
packetManagerChan chan []byte
|
||||
heroStateFactory *d2hero.HeroStateFactory
|
||||
}
|
||||
|
||||
// https://github.com/OpenDiablo2/OpenDiablo2/issues/824
|
||||
@ -68,6 +69,11 @@ func NewGameServer(asset *d2asset.AssetManager, networkServer bool,
|
||||
maxConnections = []int{8}
|
||||
}
|
||||
|
||||
heroStateFactory, err := d2hero.NewHeroStateFactory(asset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
gameServer := &GameServer{
|
||||
@ -81,6 +87,7 @@ func NewGameServer(asset *d2asset.AssetManager, networkServer bool,
|
||||
mapEngines: make([]*d2mapengine.MapEngine, 0),
|
||||
scriptEngine: d2script.CreateScriptEngine(),
|
||||
seed: time.Now().UnixNano(),
|
||||
heroStateFactory: heroStateFactory,
|
||||
}
|
||||
|
||||
// https://github.com/OpenDiablo2/OpenDiablo2/issues/827
|
||||
@ -365,6 +372,8 @@ func handleClientConnection(gameServer *GameServer, client ClientConnection, x,
|
||||
playerState.Stats,
|
||||
playerState.Skills,
|
||||
playerState.Equipment,
|
||||
playerState.LeftSkill,
|
||||
playerState.RightSkill,
|
||||
)
|
||||
|
||||
for _, connection := range gameServer.connections {
|
||||
@ -390,6 +399,8 @@ func handleClientConnection(gameServer *GameServer, client ClientConnection, x,
|
||||
conPlayerState.Stats,
|
||||
conPlayerState.Skills,
|
||||
conPlayerState.Equipment,
|
||||
conPlayerState.LeftSkill,
|
||||
conPlayerState.RightSkill,
|
||||
),
|
||||
)
|
||||
|
||||
@ -407,6 +418,7 @@ func OnClientDisconnected(client ClientConnection) {
|
||||
}
|
||||
|
||||
// OnPacketReceived is called by the local client to 'send' a packet to the server.
|
||||
// nolint:gocyclo // switch statement on packet type makes sense, no need to change
|
||||
func OnPacketReceived(client ClientConnection, packet d2netpacket.NetPacket) error {
|
||||
if singletonServer == nil {
|
||||
return errors.New("singleton server is nil")
|
||||
@ -443,6 +455,20 @@ func OnPacketReceived(client ClientConnection, packet d2netpacket.NetPacket) err
|
||||
log.Printf("GameServer: error sending %T to client %s: %s", packet, player.GetUniqueID(), err)
|
||||
}
|
||||
}
|
||||
case d2netpackettype.SavePlayer:
|
||||
savePacket, err := d2netpacket.UnmarshalSavePlayer(packet.PacketData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
playerState := singletonServer.connections[client.GetUniqueID()].GetPlayerState()
|
||||
playerState.LeftSkill = savePacket.LeftSkill
|
||||
playerState.RightSkill = savePacket.RightSkill
|
||||
|
||||
err = singletonServer.heroStateFactory.Save(playerState)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error saving saving Player: %s", err)
|
||||
}
|
||||
default:
|
||||
log.Printf("GameServer: received unknown packet %T", packet)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user