204 lines
8.0 KiB
Go
204 lines
8.0 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
|
|
"tea.melonie54.xyz/sean/go-susapp/src/enum"
|
|
"tea.melonie54.xyz/sean/go-susapp/src/gamedata"
|
|
"tea.melonie54.xyz/sean/go-susapp/src/innernetobjects"
|
|
"tea.melonie54.xyz/sean/go-susapp/src/packets"
|
|
"tea.melonie54.xyz/sean/go-susapp/src/protocol"
|
|
"tea.melonie54.xyz/sean/go-susapp/src/util"
|
|
)
|
|
|
|
type PacketProcessor struct {
|
|
sus *SusApp
|
|
gameDataProcessor *GameDataProcessor
|
|
normalPacketTagMap map[byte]func(net *protocol.PacketHandler, h *protocol.Hazel)
|
|
reliablePacketTagMap map[byte]func(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel)
|
|
}
|
|
|
|
func NewPacketProcessor(sus *SusApp) *PacketProcessor {
|
|
proc := &PacketProcessor{sus: sus, gameDataProcessor: NewGameDataProcessor(sus)}
|
|
proc.normalPacketTagMap = map[byte]func(net *protocol.PacketHandler, h *protocol.Hazel){
|
|
0x05: proc.captureUnreliableGameDataAll,
|
|
0x06: proc.captureUnreliableGameDataTo,
|
|
}
|
|
proc.reliablePacketTagMap = map[byte]func(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel){
|
|
0x00: proc.captureCreateGame,
|
|
0x01: proc.emptyCapture,
|
|
0x02: proc.captureStartGame,
|
|
0x04: proc.captureRemovePlayer,
|
|
0x05: proc.captureGameDataAll,
|
|
0x06: proc.captureGameDataTo,
|
|
0x07: proc.captureJoinedGame,
|
|
0x0a: proc.captureAlterGame,
|
|
0x0d: proc.captureRedirect,
|
|
}
|
|
return proc
|
|
}
|
|
|
|
func (proc *PacketProcessor) receiveNormalPacket(net *protocol.PacketHandler, h []*protocol.Hazel) {
|
|
for i := 0; i < len(h); i++ {
|
|
v, ok := proc.normalPacketTagMap[h[i].GetTag()]
|
|
if ok {
|
|
v(net, h[i])
|
|
} else {
|
|
fmt.Printf("Unable to parse normal packet with tag of %x\n", h[i].GetTag())
|
|
fmt.Printf("Packet %v\n", hex.EncodeToString(h[i].GetUnderlyingPacket().Dump()))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (proc *PacketProcessor) receiveReliablePacket(net *protocol.PacketHandler, nonce uint16, h []*protocol.Hazel) {
|
|
for i := 0; i < len(h); i++ {
|
|
v, ok := proc.reliablePacketTagMap[h[i].GetTag()]
|
|
if ok {
|
|
v(net, nonce, h[i])
|
|
net.SendAcknowledgementPacket(nonce, 0xff)
|
|
} else {
|
|
fmt.Printf("Unable to parse packets with tag of %x\n", h[i].GetTag())
|
|
fmt.Printf("Packet: %v\n", hex.EncodeToString(h[i].GetUnderlyingPacket().Dump()))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (proc *PacketProcessor) emptyCapture(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel) {
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureCreateGame(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel) {
|
|
a := &packets.HostGameS2C{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
|
|
proc.sus.state.TypedGameID = util.CodeFromGameID(a.GameID)
|
|
var z protocol.HazelPayload = &packets.JoinGameC2S{GameID: a.GameID}
|
|
proc.sus.networkHandler.SendReliablePacket(proc.sus.networkHandler.GetNonce(), []*protocol.Hazel{
|
|
protocol.NewHazelFromPayload(&z),
|
|
})
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureStartGame(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel) {
|
|
a := &packets.StartGameH2G{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
|
|
if a.GameID == proc.sus.state.CurrentGame.GameID {
|
|
proc.sus.state.Screen = enum.SCREEN_INGAME
|
|
proc.sus.state.LoadCollisionForMap(proc.sus.state.CurrentGame.GameOptions.Maps)
|
|
|
|
var d1 packets.GameDataSubpacket = &gamedata.ReadyC2H{ReadyClientID: proc.sus.state.CurrentGame.ClientID}
|
|
var d2 protocol.HazelPayload = packets.NewGameDataToSingleSubpacket(proc.sus.state.CurrentGame.GameID, proc.sus.state.CurrentGame.HostClientID, &d1)
|
|
net.SendReliablePacket(proc.sus.networkHandler.GetNonce(), []*protocol.Hazel{protocol.NewHazelFromPayload(&d2)})
|
|
}
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureGameDataAll(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel) {
|
|
a := &packets.GameDataAll{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
proc.gameDataProcessor.receiveGameDataSubpacket(net, a.GameID, a.Subpackets)
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureGameDataTo(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel) {
|
|
a := &packets.GameDataTo{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
|
|
if a.TargetClientID == proc.sus.state.CurrentGame.ClientID {
|
|
proc.gameDataProcessor.receiveGameDataSubpacket(net, a.GameID, a.Subpackets)
|
|
}
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureUnreliableGameDataAll(net *protocol.PacketHandler, h *protocol.Hazel) {
|
|
a := &packets.GameDataAll{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
proc.gameDataProcessor.receiveGameDataSubpacket(net, a.GameID, a.Subpackets)
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureUnreliableGameDataTo(net *protocol.PacketHandler, h *protocol.Hazel) {
|
|
a := &packets.GameDataTo{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
if a.TargetClientID == proc.sus.state.CurrentGame.ClientID {
|
|
proc.gameDataProcessor.receiveGameDataSubpacket(net, a.GameID, a.Subpackets)
|
|
}
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureJoinedGame(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel) {
|
|
a := &packets.JoinedGameH2C{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
fmt.Printf("Joined game: %v\n", a.GameID)
|
|
fmt.Printf("Client id: %v\n", a.JoinedClientID)
|
|
fmt.Printf("Host client id: %v\n", a.HostClientID)
|
|
proc.sus.state.CurrentGame = &CurrentGameData{
|
|
GameID: a.GameID,
|
|
ClientID: a.JoinedClientID,
|
|
HostClientID: a.HostClientID,
|
|
GamePrivacy: 0,
|
|
GameOptions: protocol.NewDefaultGameOptionsData(),
|
|
NetObjects: map[uint32]*innernetobjects.InnerNetObject{},
|
|
PlayerNetObjects: &PlayerNetObjectMaps{},
|
|
}
|
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerClientID = map[uint32]*PlayerObject{}
|
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerNetID = map[uint32]*PlayerObject{}
|
|
proc.sus.state.CurrentGame.OtherClientIDs = a.OtherClientIDs
|
|
proc.sus.state.Screen = enum.SCREEN_LOBBY
|
|
proc.sus.state.LoadCollision("lobby")
|
|
|
|
// Send platform
|
|
var b1 packets.GameDataSubpacket = &gamedata.ClientInfoC2S{
|
|
ClientID: proc.sus.state.CurrentGame.ClientID,
|
|
PlatformID: enum.PLATFORM_LinuxPlayer,
|
|
}
|
|
var b2 protocol.HazelPayload = packets.NewGameDataSingleSubpacket(proc.sus.state.CurrentGame.GameID, &b1)
|
|
net.SendReliablePacket(net.GetNonce(), []*protocol.Hazel{protocol.NewHazelFromPayload(&b2)})
|
|
|
|
// Send scene change
|
|
var c1 packets.GameDataSubpacket = &gamedata.SceneChangeC2H{
|
|
ClientID: proc.sus.state.CurrentGame.ClientID,
|
|
SceneName: "OnlineGame",
|
|
}
|
|
var c2 protocol.HazelPayload = packets.NewGameDataSingleSubpacket(proc.sus.state.CurrentGame.GameID, &c1)
|
|
net.SendReliablePacket(net.GetNonce(), []*protocol.Hazel{protocol.NewHazelFromPayload(&c2)})
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureAlterGame(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel) {
|
|
a := &packets.AlterGameH2G{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
fmt.Printf("Alter game: %v\n", a.GameID)
|
|
fmt.Printf("Tag ID: %v\n", a.TagID)
|
|
fmt.Printf("Tag value: %v\n", a.TagValue)
|
|
if a.GameID == proc.sus.state.CurrentGame.GameID && a.TagID == 1 {
|
|
proc.sus.state.CurrentGame.GamePrivacy = a.TagValue
|
|
}
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureRedirect(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel) {
|
|
a := &packets.RedirectS2C{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
fmt.Printf("Redirect: %v:%v", a.IPAddress.String(), a.Port)
|
|
if proc.sus.networkHandler != nil {
|
|
proc.sus.networkHandler.SendNormalDisconnectPacket()
|
|
proc.sus.networkHandler.Close()
|
|
proc.sus.networkHandler = nil
|
|
}
|
|
proc.sus.setupPacketHandler(&a.IPAddress, int(a.Port), func(ph *protocol.PacketHandler) {
|
|
fmt.Println("Sending first packet to new server")
|
|
ph.SendHelloPacket(ph.GetNonce(), 0, proc.sus.state.Version, proc.sus.state.Settings.PlayerName, 0, proc.sus.state.Settings.Language, proc.sus.state.Settings.QuickChatMode)
|
|
y, _ := util.CodeToGameID(proc.sus.state.TypedGameID)
|
|
var z protocol.HazelPayload = &packets.JoinGameC2S{GameID: y}
|
|
ph.SendReliablePacket(ph.GetNonce(), []*protocol.Hazel{
|
|
protocol.NewHazelFromPayload(&z),
|
|
})
|
|
})
|
|
}
|
|
|
|
func (proc *PacketProcessor) captureRemovePlayer(net *protocol.PacketHandler, nonce uint16, h *protocol.Hazel) {
|
|
a := &packets.RemovePlayerS2G{}
|
|
a.Read(h.GetUnderlyingPacket())
|
|
if proc.sus.state.CurrentGame != nil {
|
|
if a.GameID == proc.sus.state.CurrentGame.GameID && a.HostClientID == proc.sus.state.CurrentGame.ClientID {
|
|
fmt.Println("Host player disconnected and left me in charge")
|
|
fmt.Println("I can't host a game so I'm disconnecting too")
|
|
net.SendNormalDisconnectPacket()
|
|
}
|
|
}
|
|
}
|