1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-10-15 14:44:49 -04:00
OpenDiablo2/d2networking/d2client/game_client.go
dk fe47e51351
Refactor d2map (#468)
* WIP refactor of d2map stuff

* more d2map refactor

adding realm init to game client
passing map engine from client and server into realm at init
change `generate map packet` to have act and level index as data

* client explodes, but getting there

* realm now initializes, networking works, but map generators dont currently do anything

* changed the way that level type records are loaded

* fixed funcs for level data lookups

* started implementing level generator, currently crashing

* client no longer exploding

* d2networking refactor

put exports into d2client.go and d2server.go
kept GameClient and GameServer methods into their respective files
made methods for packet handlers instead of the giant switch statements

* bugfix: getting first level id by act

* minor refactor of gamescreen for readability

* towns now generate on server start, create player takes act and level id as args, levels have their own map engine
2020-06-26 16:50:24 -04:00

165 lines
4.6 KiB
Go

package d2client
import (
"log"
"os"
// "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2maprenderer"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
d2cct "github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
)
type GameClient struct {
clientConnection ClientConnection
connectionType d2cct.ClientConnectionType
GameState *d2player.PlayerState
MapEngine *d2mapengine.MapEngine
MapRenderer *d2maprenderer.MapRenderer
realm *d2mapengine.MapRealm
PlayerId string
Players map[string]*d2mapentity.Player
Seed int64
RegenMap bool
}
// Using the `clientConnection`, opens a connection and passes the savefile path
func (g *GameClient) Open(connectionString string, saveFilePath string) error {
return g.clientConnection.Open(connectionString, saveFilePath)
}
// Closes the `clientConnection`
func (g *GameClient) Close() error {
return g.clientConnection.Close()
}
// Closes the `clientConnection`
func (g *GameClient) Destroy() error {
return g.clientConnection.Close()
}
// Routes the incoming packets to the packet handlers
func (g *GameClient) OnPacketReceived(packet d2netpacket.NetPacket) error {
switch packet.PacketType {
// UNSURE: should we be bubbling up errors from these handler calls?
case d2netpackettype.UpdateServerInfo:
g.handleUpdateServerInfo(packet)
case d2netpackettype.AddPlayer:
g.handleAddPlayer(packet)
case d2netpackettype.GenerateMap:
g.handleGenerateMap(packet)
case d2netpackettype.MovePlayer:
g.handleMovePlayer(packet)
case d2netpackettype.Ping:
g.handlePong(packet)
case d2netpackettype.ServerClosed:
g.handleServerClosed(packet)
default:
log.Fatalf("Invalid packet type: %d", packet.PacketType)
}
return nil
}
// Using the `clientConnection`, sends a packet to the server
func (g *GameClient) SendPacketToServer(packet d2netpacket.NetPacket) error {
return g.clientConnection.SendPacketToServer(packet)
}
func (g *GameClient) handleUpdateServerInfo(p d2netpacket.NetPacket) {
serverInfo := p.PacketData.(d2netpacket.UpdateServerInfoPacket)
seed := serverInfo.Seed
playerId := serverInfo.PlayerId
g.Seed = seed
g.realm.Init(seed)
g.PlayerId = playerId
log.Printf("Player id set to %s", playerId)
}
func (g *GameClient) handleAddPlayer(p d2netpacket.NetPacket) {
player := p.PacketData.(d2netpacket.AddPlayerPacket)
levelId := g.realm.GetFirstActLevelId(player.Act)
g.MapEngine = g.realm.GetMapEngine(player.Act, levelId)
pId := player.Id
pName := player.Name
pAct := player.Act
pLvlId := levelId
pX := player.X
pY := player.Y
pDir := 0
pHero := player.HeroType
pStat := player.Stats
pEquip := player.Equipment
// UNSURE: maybe we should be passing a struct instead of all the vars?
newPlayer := d2mapentity.CreatePlayer(
pId, pName, pAct, pLvlId, pX, pY, pDir, pHero, pStat, pEquip,
)
g.Players[newPlayer.Id] = newPlayer
g.realm.AddPlayer(pId, pAct)
g.MapEngine.AddEntity(newPlayer)
}
func (g *GameClient) handleGenerateMap(p d2netpacket.NetPacket) {
mapData := p.PacketData.(d2netpacket.GenerateMapPacket)
g.realm.GenerateMap(mapData.ActId, mapData.LevelId)
engine := g.realm.GetMapEngine(mapData.ActId, mapData.LevelId)
g.MapRenderer = d2maprenderer.CreateMapRenderer(engine)
g.RegenMap = true
}
func (g *GameClient) handleMovePlayer(p d2netpacket.NetPacket) {
movePlayer := p.PacketData.(d2netpacket.MovePlayerPacket)
player := g.Players[movePlayer.PlayerId]
x1, y1 := movePlayer.StartX, movePlayer.StartY
x2, y2 := movePlayer.DestX, movePlayer.DestY
path, _, _ := g.MapEngine.PathFind(x1, y1, x2, y2)
if len(path) > 0 {
player.SetPath(path, func() {
tile := g.MapEngine.TileAt(player.TileX, player.TileY)
if tile == nil {
return
}
regionType := tile.RegionType
if regionType == d2enum.RegionAct1Town {
player.SetIsInTown(true)
} else {
player.SetIsInTown(false)
}
player.SetAnimationMode(player.GetAnimationMode().String())
})
}
}
func (g *GameClient) handlePong(p d2netpacket.NetPacket) {
pong := d2netpacket.CreatePongPacket(g.PlayerId)
g.clientConnection.SendPacketToServer(pong)
}
func (g *GameClient) handleServerClosed(p d2netpacket.NetPacket) {
// TODO: Need to be tied into a character save and exit
log.Print("Server has been closed")
os.Exit(0)
}