mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-09 01:56:47 -05:00
D2networking resolve lint issues (#497)
* Added automap.go stub * Handle errors in original AutoMap.txt file * Completed AutoMapRecord struct and comments * AutoMap loader implemented * Update from base repo * Comments added to d2netpacket and d2netpackettype. Note, the Overview for d2netpacket is in net_packet.go. It could be placed in a doc.go file but net_packet.go seemed appropriate in this case. * Comments added to d2server * client_connection.go missed from previous commit * Comments added to d2client * Doc.go added to d2networking and other corrections * Unused parameter present to satisfy interface, named it '_' * Unhandled errors and other issues resolved in d2networking. This commit adds simple error reporting and creates a lot of mess. I will be doing one more pass to tidy things up a bit before I move on. * Commented out continue on RemoteClientConnection error and implemented stringer in message type * NetPacketType.String uses map instead of switch. * Map moved into String method
This commit is contained in:
parent
ae6bfb839e
commit
c27fb572bc
@ -2,6 +2,8 @@
|
||||
package d2localclient
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
||||
@ -47,7 +49,7 @@ func Create(openNetworkServer bool) *LocalClientConnection {
|
||||
}
|
||||
|
||||
// Open creates a new GameServer, runs the server and connects this client to it.
|
||||
func (l *LocalClientConnection) Open(connectionString string, saveFilePath string) error {
|
||||
func (l *LocalClientConnection) Open(_ string, saveFilePath string) error {
|
||||
l.SetPlayerState(d2player.LoadPlayerState(saveFilePath))
|
||||
d2server.Create(l.openNetworkServer)
|
||||
go d2server.Run()
|
||||
@ -57,7 +59,10 @@ func (l *LocalClientConnection) Open(connectionString string, saveFilePath strin
|
||||
|
||||
// Close disconnects from the server and destroys it.
|
||||
func (l *LocalClientConnection) Close() error {
|
||||
l.SendPacketToServer(d2netpacket.CreateServerClosedPacket())
|
||||
err := l.SendPacketToServer(d2netpacket.CreateServerClosedPacket())
|
||||
if err != nil {
|
||||
log.Printf("LocalClientConnection: error sending ServerClosedPacket to server: %s", err)
|
||||
}
|
||||
d2server.OnClientDisconnected(l)
|
||||
d2server.Destroy()
|
||||
return nil
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@ -82,7 +83,11 @@ func (l *RemoteClientConnection) Open(connectionString string, saveFilePath stri
|
||||
|
||||
log.Printf("Connected to server at %s", l.udpConnection.RemoteAddr().String())
|
||||
gameState := d2player.LoadPlayerState(saveFilePath)
|
||||
l.SendPacketToServer(d2netpacket.CreatePlayerConnectionRequestPacket(l.GetUniqueId(), gameState))
|
||||
err = l.SendPacketToServer(d2netpacket.CreatePlayerConnectionRequestPacket(l.GetUniqueId(), gameState))
|
||||
if err != nil {
|
||||
log.Print("RemoteClientConnection: error sending PlayerConnectionRequestPacket to server.")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -91,7 +96,10 @@ func (l *RemoteClientConnection) Open(connectionString string, saveFilePath stri
|
||||
// RemoteClientConnection.active to false.
|
||||
func (l *RemoteClientConnection) Close() error {
|
||||
l.active = false
|
||||
l.SendPacketToServer(d2netpacket.CreatePlayerDisconnectRequestPacket(l.GetUniqueId()))
|
||||
err := l.SendPacketToServer(d2netpacket.CreatePlayerDisconnectRequestPacket(l.GetUniqueId()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -106,8 +114,15 @@ func (l *RemoteClientConnection) SendPacketToServer(packet d2netpacket.NetPacket
|
||||
var buff bytes.Buffer
|
||||
buff.WriteByte(byte(packet.PacketType))
|
||||
writer, _ := gzip.NewWriterLevel(&buff, gzip.BestCompression)
|
||||
writer.Write(data)
|
||||
writer.Close()
|
||||
|
||||
if written, err := writer.Write(data); err != nil {
|
||||
return err
|
||||
} else if written == 0 {
|
||||
return errors.New(fmt.Sprintf("RemoteClientConnection: attempted to send empty %v packet body.", packet.PacketType))
|
||||
}
|
||||
if err = writer.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = l.udpConnection.Write(buff.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -137,42 +152,87 @@ func (l *RemoteClientConnection) serverListener() {
|
||||
packetType := d2netpackettype.NetPacketType(packetTypeId)
|
||||
reader, err := gzip.NewReader(buff)
|
||||
sb := new(strings.Builder)
|
||||
io.Copy(sb, reader)
|
||||
written, err := io.Copy(sb, reader)
|
||||
if err != nil {
|
||||
log.Printf("RemoteClientConnection: error copying bytes from %v packet: %s", packetType, err)
|
||||
// TODO: All packets coming from the client seem to be throwing an error
|
||||
//continue
|
||||
}
|
||||
if written == 0 {
|
||||
log.Printf("RemoteClientConnection: empty packet %v packet received", packetType)
|
||||
continue
|
||||
}
|
||||
|
||||
stringData := sb.String()
|
||||
switch packetType {
|
||||
case d2netpackettype.GenerateMap:
|
||||
var packet d2netpacket.GenerateMapPacket
|
||||
json.Unmarshal([]byte(stringData), &packet)
|
||||
l.SendPacketToClient(d2netpacket.NetPacket{
|
||||
err := json.Unmarshal([]byte(stringData), &packet)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error unmarshalling %T: %s", packet, err)
|
||||
continue
|
||||
}
|
||||
err = l.SendPacketToClient(d2netpacket.NetPacket{
|
||||
PacketType: packetType,
|
||||
PacketData: packet,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("RemoteClientConnection: error processing packet %v: %s", packetType, err)
|
||||
}
|
||||
case d2netpackettype.MovePlayer:
|
||||
var packet d2netpacket.MovePlayerPacket
|
||||
json.Unmarshal([]byte(stringData), &packet)
|
||||
l.SendPacketToClient(d2netpacket.NetPacket{
|
||||
err := json.Unmarshal([]byte(stringData), &packet)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error unmarshalling %T: %s", packet, err)
|
||||
continue
|
||||
}
|
||||
err = l.SendPacketToClient(d2netpacket.NetPacket{
|
||||
PacketType: packetType,
|
||||
PacketData: packet,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("RemoteClientConnection: error processing packet %v: %s", packetType, err)
|
||||
}
|
||||
case d2netpackettype.UpdateServerInfo:
|
||||
var packet d2netpacket.UpdateServerInfoPacket
|
||||
json.Unmarshal([]byte(stringData), &packet)
|
||||
l.SendPacketToClient(d2netpacket.NetPacket{
|
||||
err := json.Unmarshal([]byte(stringData), &packet)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error unmarshalling %T: %s", packet, err)
|
||||
continue
|
||||
}
|
||||
err = l.SendPacketToClient(d2netpacket.NetPacket{
|
||||
PacketType: packetType,
|
||||
PacketData: packet,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("RemoteClientConnection: error processing packet %v: %s", packetType, err)
|
||||
}
|
||||
case d2netpackettype.AddPlayer:
|
||||
var packet d2netpacket.AddPlayerPacket
|
||||
json.Unmarshal([]byte(stringData), &packet)
|
||||
l.SendPacketToClient(d2netpacket.NetPacket{
|
||||
err := json.Unmarshal([]byte(stringData), &packet)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error unmarshalling %T: %s", packet, err)
|
||||
continue
|
||||
}
|
||||
err = l.SendPacketToClient(d2netpacket.NetPacket{
|
||||
PacketType: packetType,
|
||||
PacketData: packet,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("RemoteClientConnection: error processing packet %v: %s", packetType, err)
|
||||
}
|
||||
case d2netpackettype.Ping:
|
||||
l.SendPacketToServer(d2netpacket.CreatePongPacket(l.uniqueId))
|
||||
err := l.SendPacketToServer(d2netpacket.CreatePongPacket(l.uniqueId))
|
||||
if err != nil {
|
||||
log.Printf("RemoteClientConnection: error responding to server ping: %s", err)
|
||||
}
|
||||
case d2netpackettype.PlayerDisconnectionNotification:
|
||||
var packet d2netpacket.PlayerDisconnectRequestPacket
|
||||
json.Unmarshal([]byte(stringData), &packet)
|
||||
err := json.Unmarshal([]byte(stringData), &packet)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error unmarshalling %T: %s", packet, err)
|
||||
continue
|
||||
}
|
||||
log.Printf("Received disconnect: %s", packet.Id)
|
||||
default:
|
||||
fmt.Printf("Unknown packet type %d\n", packetType)
|
||||
|
@ -114,7 +114,10 @@ func (g *GameClient) OnPacketReceived(packet d2netpacket.NetPacket) error {
|
||||
} else {
|
||||
player.SetIsInTown(false)
|
||||
}
|
||||
player.SetAnimationMode(player.GetAnimationMode().String())
|
||||
err := player.SetAnimationMode(player.GetAnimationMode().String())
|
||||
if err != nil {
|
||||
log.Printf("GameClient: error setting animation mode for player %s: %s", player.Id, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
case d2netpackettype.CastSkill:
|
||||
@ -145,7 +148,11 @@ func (g *GameClient) OnPacketReceived(packet d2netpacket.NetPacket) error {
|
||||
|
||||
g.MapEngine.AddEntity(missile)
|
||||
case d2netpackettype.Ping:
|
||||
g.clientConnection.SendPacketToServer(d2netpacket.CreatePongPacket(g.PlayerId))
|
||||
err := g.clientConnection.SendPacketToServer(d2netpacket.CreatePongPacket(g.PlayerId))
|
||||
if err != nil {
|
||||
log.Printf("GameClient: error responding to server ping: %s", err)
|
||||
}
|
||||
|
||||
case d2netpackettype.ServerClosed:
|
||||
// TODO: Need to be tied into a character save and exit
|
||||
log.Print("Server has been closed")
|
||||
|
@ -5,7 +5,7 @@ package d2netpackettype
|
||||
// d2netpacket.
|
||||
type NetPacketType uint32
|
||||
|
||||
//(Except NetPacket which declares a NetPacketType to specify the packet body
|
||||
// (Except NetPacket which declares a NetPacketType to specify the packet body
|
||||
// type. See d2netpackettype.NetPacket.)
|
||||
//
|
||||
// Warning
|
||||
@ -26,3 +26,20 @@ const (
|
||||
ServerClosed // Sent by the local host when it has closed the server
|
||||
CastSkill // Sent by client or server, indicates entity casting skill
|
||||
)
|
||||
|
||||
func (n NetPacketType) String() string {
|
||||
strings := map[NetPacketType]string{
|
||||
UpdateServerInfo: "UpdateServerInfo",
|
||||
GenerateMap: "GenerateMap",
|
||||
AddPlayer: "AddPlayer",
|
||||
MovePlayer: "MovePlayer",
|
||||
PlayerConnectionRequest: "PlayerConnectionRequest",
|
||||
PlayerDisconnectionNotification: "PlayerDisconnectionNotification",
|
||||
Ping: "Ping",
|
||||
Pong: "Pong",
|
||||
ServerClosed: "ServerClosed",
|
||||
CastSkill: "CastSkill",
|
||||
}
|
||||
|
||||
return strings[n]
|
||||
}
|
||||
|
@ -85,7 +85,10 @@ func (c *ConnectionManager) Shutdown() {
|
||||
// Things can be done more cleanly once we have graceful exits however we still need to account for other OS Signals
|
||||
log.Print("Notifying clients server is shutting down...")
|
||||
for _, connection := range c.gameServer.clientConnections {
|
||||
connection.SendPacketToClient(d2netpacket.CreateServerClosedPacket())
|
||||
err := connection.SendPacketToClient(d2netpacket.CreateServerClosedPacket())
|
||||
if err != nil {
|
||||
log.Printf("ConnectionManager: error sending ServerClosedPacket to client ID %s: %s", connection.GetUniqueId(), err)
|
||||
}
|
||||
}
|
||||
Stop()
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
||||
@ -57,10 +59,16 @@ func (u *UDPClientConnection) SendPacketToClient(packet d2netpacket.NetPacket) e
|
||||
var buff bytes.Buffer
|
||||
buff.WriteByte(byte(packet.PacketType))
|
||||
writer, _ := gzip.NewWriterLevel(&buff, gzip.BestCompression)
|
||||
writer.Write(data)
|
||||
writer.Close()
|
||||
_, err = u.udpConnection.WriteToUDP(buff.Bytes(), u.address)
|
||||
if err != nil {
|
||||
|
||||
if written, err := writer.Write(data); err != nil {
|
||||
return err
|
||||
} else if written == 0 {
|
||||
return errors.New(fmt.Sprintf("RemoteClientConnection: attempted to send empty %v packet body.", packet.PacketType))
|
||||
}
|
||||
if err = writer.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = u.udpConnection.WriteToUDP(buff.Bytes(), u.address); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,10 @@ func createNetworkServer() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
singletonServer.udpConnection.SetReadBuffer(4096)
|
||||
err = singletonServer.udpConnection.SetReadBuffer(4096)
|
||||
if err != nil {
|
||||
log.Print("GameServer: error setting UDP read buffer:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// runNetworkServer runs a while loop, reading from the GameServer's UDP
|
||||
@ -107,35 +110,63 @@ func runNetworkServer() {
|
||||
packetType := d2netpackettype.NetPacketType(packetTypeId)
|
||||
reader, err := gzip.NewReader(buff)
|
||||
sb := new(strings.Builder)
|
||||
io.Copy(sb, reader)
|
||||
written, err := io.Copy(sb, reader)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error copying bytes from %v packet: %s", packetType, err)
|
||||
continue
|
||||
}
|
||||
if written == 0 {
|
||||
log.Printf("GameServer: empty packet %v packet received", packetType)
|
||||
continue
|
||||
}
|
||||
|
||||
stringData := sb.String()
|
||||
switch packetType {
|
||||
case d2netpackettype.PlayerConnectionRequest:
|
||||
packetData := d2netpacket.PlayerConnectionRequestPacket{}
|
||||
json.Unmarshal([]byte(stringData), &packetData)
|
||||
err := json.Unmarshal([]byte(stringData), &packetData)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error unmarshalling packet of type %T: %s", packetData, err)
|
||||
continue
|
||||
}
|
||||
clientConnection := d2udpclientconnection.CreateUDPClientConnection(singletonServer.udpConnection, packetData.Id, addr)
|
||||
clientConnection.SetPlayerState(packetData.PlayerState)
|
||||
OnClientConnected(clientConnection)
|
||||
case d2netpackettype.MovePlayer:
|
||||
packetData := d2netpacket.MovePlayerPacket{}
|
||||
json.Unmarshal([]byte(stringData), &packetData)
|
||||
err := json.Unmarshal([]byte(stringData), &packetData)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error unmarshalling %T: %s", packetData, err)
|
||||
continue
|
||||
}
|
||||
netPacket := d2netpacket.NetPacket{
|
||||
PacketType: packetType,
|
||||
PacketData: packetData,
|
||||
}
|
||||
|
||||
for _, player := range singletonServer.clientConnections {
|
||||
player.SendPacketToClient(netPacket)
|
||||
err = player.SendPacketToClient(netPacket)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error sending %T to client %s: %s", packetData, player.GetUniqueId(), err)
|
||||
}
|
||||
}
|
||||
case d2netpackettype.Pong:
|
||||
packetData := d2netpacket.PlayerConnectionRequestPacket{}
|
||||
json.Unmarshal([]byte(stringData), &packetData)
|
||||
err := json.Unmarshal([]byte(stringData), &packetData)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error unmarshalling packet of type %T: %s", packetData, err)
|
||||
continue
|
||||
}
|
||||
singletonServer.manager.Recv(packetData.Id)
|
||||
case d2netpackettype.ServerClosed:
|
||||
singletonServer.manager.Shutdown()
|
||||
case d2netpackettype.PlayerDisconnectionNotification:
|
||||
var packet d2netpacket.PlayerDisconnectRequestPacket
|
||||
json.Unmarshal([]byte(stringData), &packet)
|
||||
err := json.Unmarshal([]byte(stringData), &packet)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error unmarshalling packet of type %T: %s", packet, err)
|
||||
continue
|
||||
}
|
||||
log.Printf("Received disconnect: %s", packet.Id)
|
||||
}
|
||||
}
|
||||
@ -146,7 +177,10 @@ func runNetworkServer() {
|
||||
func Run() {
|
||||
log.Print("Starting GameServer")
|
||||
singletonServer.running = true
|
||||
singletonServer.scriptEngine.RunScript("scripts/server/server.js")
|
||||
_, err := singletonServer.scriptEngine.RunScript("scripts/server/server.js")
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error initializing debug script: %s", err)
|
||||
}
|
||||
if singletonServer.udpConnection != nil {
|
||||
go runNetworkServer()
|
||||
}
|
||||
@ -159,7 +193,10 @@ func Stop() {
|
||||
log.Print("Stopping GameServer")
|
||||
singletonServer.running = false
|
||||
if singletonServer.udpConnection != nil {
|
||||
singletonServer.udpConnection.Close()
|
||||
err := singletonServer.udpConnection.Close()
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error when trying to close UDP connection: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,21 +227,33 @@ func OnClientConnected(client ClientConnection) {
|
||||
|
||||
log.Printf("Client connected with an id of %s", client.GetUniqueId())
|
||||
singletonServer.clientConnections[client.GetUniqueId()] = client
|
||||
client.SendPacketToClient(d2netpacket.CreateUpdateServerInfoPacket(singletonServer.seed, client.GetUniqueId()))
|
||||
client.SendPacketToClient(d2netpacket.CreateGenerateMapPacket(d2enum.RegionAct1Town))
|
||||
err := client.SendPacketToClient(d2netpacket.CreateUpdateServerInfoPacket(singletonServer.seed, client.GetUniqueId()))
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error sending UpdateServerInfoPacket to client %s: %s", client.GetUniqueId(), err)
|
||||
}
|
||||
err = client.SendPacketToClient(d2netpacket.CreateGenerateMapPacket(d2enum.RegionAct1Town))
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error sending GenerateMapPacket to client %s: %s", client.GetUniqueId(), err)
|
||||
}
|
||||
|
||||
playerState := client.GetPlayerState()
|
||||
createPlayerPacket := d2netpacket.CreateAddPlayerPacket(client.GetUniqueId(), playerState.HeroName, int(sx*5)+3, int(sy*5)+3,
|
||||
playerState.HeroType, *playerState.Stats, playerState.Equipment)
|
||||
for _, connection := range singletonServer.clientConnections {
|
||||
connection.SendPacketToClient(createPlayerPacket)
|
||||
err := connection.SendPacketToClient(createPlayerPacket)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error sending %T to client %s: %s", createPlayerPacket, connection.GetUniqueId(), err)
|
||||
}
|
||||
if connection.GetUniqueId() == client.GetUniqueId() {
|
||||
continue
|
||||
}
|
||||
|
||||
conPlayerState := connection.GetPlayerState()
|
||||
client.SendPacketToClient(d2netpacket.CreateAddPlayerPacket(connection.GetUniqueId(), conPlayerState.HeroName,
|
||||
err = client.SendPacketToClient(d2netpacket.CreateAddPlayerPacket(connection.GetUniqueId(), conPlayerState.HeroName,
|
||||
int(conPlayerState.X*5)+3, int(conPlayerState.Y*5)+3, conPlayerState.HeroType, *conPlayerState.Stats, conPlayerState.Equipment))
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error sending CreateAddPlayerPacket to client %s: %s", connection.GetUniqueId(), err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -228,11 +277,17 @@ func OnPacketReceived(client ClientConnection, packet d2netpacket.NetPacket) err
|
||||
playerState.Y = packet.PacketData.(d2netpacket.MovePlayerPacket).DestY
|
||||
// ----------------------------------------------------------------
|
||||
for _, player := range singletonServer.clientConnections {
|
||||
player.SendPacketToClient(packet)
|
||||
err := player.SendPacketToClient(packet)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error sending %T to client %s: %s", packet, player.GetUniqueId(), err)
|
||||
}
|
||||
}
|
||||
case d2netpackettype.CastSkill:
|
||||
for _, player := range singletonServer.clientConnections {
|
||||
player.SendPacketToClient(packet)
|
||||
err := player.SendPacketToClient(packet)
|
||||
if err != nil {
|
||||
log.Printf("GameServer: error sending %T to client %s: %s", packet, player.GetUniqueId(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user