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:
danhale-git 2020-07-01 01:01:51 +01:00 committed by GitHub
parent ae6bfb839e
commit c27fb572bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 195 additions and 40 deletions

View File

@ -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

View File

@ -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)

View File

@ -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")

View File

@ -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]
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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