mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-18 02:16:23 -05:00
3936e01afb
Make sure connections close properly, without weird error messages Remove player map entity when a player disconnects from a multiplayer game Close server properly when host disconnects, handle ServerClose on remote clients Don't mix JSON decoders and raw TCP writes Actually handle incoming packets from remote clients General code cleanup for simplicity and consistency
122 lines
3.7 KiB
Go
122 lines
3.7 KiB
Go
package d2localclient
|
|
|
|
import (
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2server"
|
|
)
|
|
|
|
// LocalClientConnection is the implementation of ClientConnection
|
|
// for a local client.
|
|
type LocalClientConnection struct {
|
|
asset *d2asset.AssetManager
|
|
heroState *d2hero.HeroStateFactory
|
|
clientListener d2networking.ClientListener // The game client
|
|
uniqueID string // Unique ID generated on construction
|
|
openNetworkServer bool // True if this is a server
|
|
playerState *d2hero.HeroState // Local player state
|
|
gameServer *d2server.GameServer // Game Server
|
|
|
|
logLevel d2util.LogLevel
|
|
}
|
|
|
|
// GetUniqueID returns LocalClientConnection.uniqueID.
|
|
func (l *LocalClientConnection) GetUniqueID() string {
|
|
return l.uniqueID
|
|
}
|
|
|
|
// GetConnectionType returns an enum representing the connection type.
|
|
// See: d2clientconnectiontype
|
|
func (l *LocalClientConnection) GetConnectionType() d2clientconnectiontype.ClientConnectionType {
|
|
return d2clientconnectiontype.Local
|
|
}
|
|
|
|
// SendPacketToClient passes a packet to the game client for processing.
|
|
func (l *LocalClientConnection) SendPacketToClient(packet d2netpacket.NetPacket) error {
|
|
return l.clientListener.OnPacketReceived(packet)
|
|
}
|
|
|
|
// Create constructs a new LocalClientConnection and returns
|
|
// a pointer to it.
|
|
func Create(
|
|
asset *d2asset.AssetManager,
|
|
l d2util.LogLevel,
|
|
openNetworkServer bool) (*LocalClientConnection, error) {
|
|
heroStateFactory, err := d2hero.NewHeroStateFactory(asset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result := &LocalClientConnection{
|
|
heroState: heroStateFactory,
|
|
asset: asset,
|
|
uniqueID: uuid.New().String(),
|
|
openNetworkServer: openNetworkServer,
|
|
logLevel: l,
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// Open creates a new GameServer, runs the server and connects this client to it.
|
|
func (l *LocalClientConnection) Open(_, saveFilePath string) error {
|
|
var err error
|
|
|
|
l.SetPlayerState(l.heroState.LoadHeroState(saveFilePath))
|
|
|
|
l.gameServer, err = d2server.NewGameServer(l.asset, l.openNetworkServer, l.logLevel, 30)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := l.gameServer.Start(); err != nil {
|
|
return err
|
|
}
|
|
|
|
l.gameServer.OnClientConnected(l)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Close disconnects from the server and destroys it.
|
|
func (l *LocalClientConnection) Close() error {
|
|
disconnectRequest, err := d2netpacket.CreatePlayerDisconnectRequestPacket(l.uniqueID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = l.SendPacketToServer(disconnectRequest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SendPacketToServer calls d2server.OnPacketReceived with the given packet.
|
|
func (l *LocalClientConnection) SendPacketToServer(packet d2netpacket.NetPacket) error {
|
|
return l.gameServer.OnPacketReceived(l, packet)
|
|
}
|
|
|
|
// SetClientListener sets LocalClientConnection.clientListener to the given value.
|
|
func (l *LocalClientConnection) SetClientListener(listener d2networking.ClientListener) {
|
|
l.clientListener = listener
|
|
}
|
|
|
|
// GetPlayerState returns LocalClientConnection.playerState.
|
|
func (l *LocalClientConnection) GetPlayerState() *d2hero.HeroState {
|
|
return l.playerState
|
|
}
|
|
|
|
// SetPlayerState sets LocalClientConnection.playerState to the given value.
|
|
func (l *LocalClientConnection) SetPlayerState(playerState *d2hero.HeroState) {
|
|
l.playerState = playerState
|
|
}
|