First commit
This commit is contained in:
commit
4ec1b9bdb7
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
dist/
|
||||||
|
package/
|
9
LICENSE
Normal file
9
LICENSE
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Copyright 2020 Sean
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
Makefile
Normal file
26
Makefile
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
|
||||||
|
all:
|
||||||
|
make build-main
|
||||||
|
|
||||||
|
build-main:
|
||||||
|
mkdir -p dist/ && go build -o dist/susapp .
|
||||||
|
|
||||||
|
package:
|
||||||
|
./scripts/package-susapp.sh
|
||||||
|
|
||||||
|
deb:
|
||||||
|
make clean && \
|
||||||
|
make all && \
|
||||||
|
make package
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf dist/ && \
|
||||||
|
rm -rf package/
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: run
|
||||||
|
run:
|
||||||
|
make && \
|
||||||
|
cd ./dist/ && \
|
||||||
|
./susapp
|
1
assets/collision/airship.json
Normal file
1
assets/collision/airship.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/collision/mira.json
Normal file
1
assets/collision/mira.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/collision/polus.json
Normal file
1
assets/collision/polus.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/collision/skeld.json
Normal file
1
assets/collision/skeld.json
Normal file
File diff suppressed because one or more lines are too long
157
gamedataprocessor.go
Normal file
157
gamedataprocessor.go
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/gamedata"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/innernetobjects"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/mapdata"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/packets"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GameDataProcessor struct {
|
||||||
|
sus *SusApp
|
||||||
|
gameRpcProcessor *GameRPCProcessor
|
||||||
|
subpacketTagMap map[byte]func(net *protocol.PacketHandler, GameID int32, h *protocol.Hazel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGameDataProcessor(sus *SusApp) *GameDataProcessor {
|
||||||
|
proc := &GameDataProcessor{sus: sus, gameRpcProcessor: NewGameRPCProcessor(sus)}
|
||||||
|
proc.subpacketTagMap = map[byte]func(net *protocol.PacketHandler, GameID int32, h *protocol.Hazel){
|
||||||
|
0x01: proc.captureGameData,
|
||||||
|
0x02: proc.captureGameRPC,
|
||||||
|
0x04: proc.captureGameSpawn,
|
||||||
|
0x05: proc.captureGameDespawn,
|
||||||
|
}
|
||||||
|
return proc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameDataProcessor) receiveGameDataSubpacket(net *protocol.PacketHandler, GameID int32, h []*protocol.Hazel) {
|
||||||
|
for i := 0; i < len(h); i++ {
|
||||||
|
v, ok := proc.subpacketTagMap[h[i].GetTag()]
|
||||||
|
if ok {
|
||||||
|
v(net, GameID, h[i])
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Unable to parse gamedata subpackets with tag of %x\n", h[i].GetTag())
|
||||||
|
fmt.Printf("Packet: %v\n", hex.EncodeToString(h[i].GetUnderlyingPacket().Dump()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameDataProcessor) captureGameData(net *protocol.PacketHandler, GameID int32, h *protocol.Hazel) {
|
||||||
|
a := &gamedata.DataH2G{}
|
||||||
|
a.Read(h.GetUnderlyingPacket())
|
||||||
|
|
||||||
|
netId := a.Component.NetID
|
||||||
|
if netId != 0 {
|
||||||
|
b, ok := proc.sus.state.CurrentGame.NetObjects[netId]
|
||||||
|
if ok {
|
||||||
|
(*b).Read(a.Component.RawData, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameDataProcessor) captureGameRPC(net *protocol.PacketHandler, GameID int32, h *protocol.Hazel) {
|
||||||
|
proc.gameRpcProcessor.receiveGameRpcCall(net, GameID, gamedata.NewRpcFromHazel(h))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameDataProcessor) captureGameSpawn(net *protocol.PacketHandler, GameID int32, h *protocol.Hazel) {
|
||||||
|
a := &gamedata.SpawnH2G{}
|
||||||
|
a.Read(h.GetUnderlyingPacket())
|
||||||
|
|
||||||
|
if len(a.Components) >= 1 {
|
||||||
|
z := a.Components[0]
|
||||||
|
netId := z.NetID
|
||||||
|
switch a.SpawnType {
|
||||||
|
case enum.SPAWNTYPE_GAME_DATA:
|
||||||
|
b := &innernetobjects.GameData{}
|
||||||
|
b.Read(z.ComponentData.GetUnderlyingPacket(), true)
|
||||||
|
var c innernetobjects.InnerNetObject = b
|
||||||
|
proc.sus.state.CurrentGame.NetObjects[netId] = &c
|
||||||
|
proc.sus.state.CurrentGame.GameDataNetID = netId
|
||||||
|
fmt.Printf("GameData Net ID: %v\n", netId)
|
||||||
|
case enum.SPAWNTYPE_SKELD_SHIP_STATUS:
|
||||||
|
b := innernetobjects.NewSkeldShipStatus()
|
||||||
|
b.Read(z.ComponentData.GetUnderlyingPacket(), true)
|
||||||
|
var c innernetobjects.InnerNetObject = b
|
||||||
|
proc.sus.state.CurrentGame.NetObjects[netId] = &c
|
||||||
|
proc.sus.state.CurrentGame.MapNetObjectNetID = netId
|
||||||
|
fmt.Printf("SkeldShipStatus Net ID: %v\n", netId)
|
||||||
|
case enum.SPAWNTYPE_MIRA_SHIP_STATUS:
|
||||||
|
b := innernetobjects.NewMiraShipStatus()
|
||||||
|
b.Read(z.ComponentData.GetUnderlyingPacket(), true)
|
||||||
|
var c innernetobjects.InnerNetObject = b
|
||||||
|
proc.sus.state.CurrentGame.NetObjects[netId] = &c
|
||||||
|
proc.sus.state.CurrentGame.MapNetObjectNetID = netId
|
||||||
|
fmt.Printf("MiraShipStatus Net ID: %v\n", netId)
|
||||||
|
case enum.SPAWNTYPE_POLUS_SHIP_STATUS:
|
||||||
|
b := innernetobjects.NewPolusShipStatus()
|
||||||
|
b.Read(z.ComponentData.GetUnderlyingPacket(), true)
|
||||||
|
var c innernetobjects.InnerNetObject = b
|
||||||
|
proc.sus.state.CurrentGame.NetObjects[netId] = &c
|
||||||
|
proc.sus.state.CurrentGame.MapNetObjectNetID = netId
|
||||||
|
fmt.Printf("PolusShipStatus Net ID: %v\n", netId)
|
||||||
|
case enum.SPAWNTYPE_PLAYER_CONTROL:
|
||||||
|
b := &innernetobjects.PlayerControl{}
|
||||||
|
b.Read(z.ComponentData.GetUnderlyingPacket(), true)
|
||||||
|
var c innernetobjects.InnerNetObject = b
|
||||||
|
proc.sus.state.CurrentGame.NetObjects[netId] = &c
|
||||||
|
y := &PlayerObject{}
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerNetID[netId] = y
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerClientID[a.OwnerID] = y
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerClientID[a.OwnerID].PlayerClientNetID = netId
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerClientID[a.OwnerID].PlayerControllerNetID = netId
|
||||||
|
fmt.Printf("Player Net ID: %v\n", netId)
|
||||||
|
fmt.Printf("Player Owner ID: %v\n", a.OwnerID)
|
||||||
|
|
||||||
|
isMyPlayer := a.OwnerID == proc.sus.state.CurrentGame.ClientID
|
||||||
|
if isMyPlayer {
|
||||||
|
fmt.Println("Owner ID matches current Client ID so its my player controller")
|
||||||
|
proc.sus.state.CurrentGame.ClientPlayerNetID = z.NetID
|
||||||
|
|
||||||
|
// Send RPC CheckName
|
||||||
|
proc.sus.state.CurrentGame.CheckNameNonce = net.GetNonce()
|
||||||
|
var d1 gamedata.RpcSub = &gamedata.RpcCheckName{Name: proc.sus.state.Settings.PlayerName}
|
||||||
|
var d2 packets.GameDataSubpacket = gamedata.NewRpcFromRpcSub(proc.sus.state.CurrentGame.ClientPlayerNetID, &d1)
|
||||||
|
var d3 protocol.HazelPayload = packets.NewGameDataToSingleSubpacket(proc.sus.state.CurrentGame.GameID, proc.sus.state.CurrentGame.HostClientID, &d2)
|
||||||
|
net.SendReliablePacket(proc.sus.state.CurrentGame.CheckNameNonce, []*protocol.Hazel{protocol.NewHazelFromPayload(&d3)})
|
||||||
|
|
||||||
|
// Send RPC CheckColor
|
||||||
|
proc.sus.state.CurrentGame.CheckColorNonce = net.GetNonce()
|
||||||
|
var e1 gamedata.RpcSub = &gamedata.RpcCheckColor{Color: proc.sus.state.Settings.PlayerColor}
|
||||||
|
var e2 packets.GameDataSubpacket = gamedata.NewRpcFromRpcSub(proc.sus.state.CurrentGame.ClientPlayerNetID, &e1)
|
||||||
|
var e3 protocol.HazelPayload = packets.NewGameDataToSingleSubpacket(proc.sus.state.CurrentGame.GameID, proc.sus.state.CurrentGame.HostClientID, &e2)
|
||||||
|
net.SendReliablePacket(proc.sus.state.CurrentGame.CheckColorNonce, []*protocol.Hazel{protocol.NewHazelFromPayload(&e3)})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(a.Components) >= 2 {
|
||||||
|
y := a.Components[1].NetID
|
||||||
|
d := innernetobjects.PlayerPhysics{}
|
||||||
|
d.Read(a.Components[1].ComponentData.GetUnderlyingPacket(), true)
|
||||||
|
var e innernetobjects.InnerNetObject = &d
|
||||||
|
proc.sus.state.CurrentGame.NetObjects[y] = &e
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerClientID[a.OwnerID].PlayerPhysicsNetID = y
|
||||||
|
}
|
||||||
|
if len(a.Components) >= 3 {
|
||||||
|
y := a.Components[2].NetID
|
||||||
|
d := innernetobjects.PlayerNetworkTransform{}
|
||||||
|
d.Read(a.Components[2].ComponentData.GetUnderlyingPacket(), true)
|
||||||
|
var e innernetobjects.InnerNetObject = &d
|
||||||
|
proc.sus.state.CurrentGame.NetObjects[y] = &e
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerClientID[a.OwnerID].PlayerNetworkTransform = y
|
||||||
|
|
||||||
|
if isMyPlayer {
|
||||||
|
d.TargetPosition = mapdata.LobbySpawnPositions[int(b.PlayerID)%len(mapdata.LobbySpawnPositions)]
|
||||||
|
proc.sus.movementProcessor.Tick(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameDataProcessor) captureGameDespawn(net *protocol.PacketHandler, GameID int32, h *protocol.Hazel) {
|
||||||
|
|
||||||
|
}
|
101
gamerpcprocessor.go
Normal file
101
gamerpcprocessor.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/gamedata"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GameRPCProcessor struct {
|
||||||
|
sus *SusApp
|
||||||
|
rpcCallMap map[byte]func(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGameRPCProcessor(sus *SusApp) *GameRPCProcessor {
|
||||||
|
proc := &GameRPCProcessor{sus: sus}
|
||||||
|
proc.rpcCallMap = map[byte]func(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc){
|
||||||
|
0x00: proc.captureRpcPlayAnimation,
|
||||||
|
0x02: proc.captureRpcSyncSettings,
|
||||||
|
0x03: proc.captureRpcSetInfected,
|
||||||
|
0x04: proc.captureRpcExiled,
|
||||||
|
0x06: proc.captureRpcSetName,
|
||||||
|
0x08: proc.captureRpcSetColor,
|
||||||
|
0x09: proc.captureRpcSetHat,
|
||||||
|
0x0a: proc.captureRpcSetSkin,
|
||||||
|
0x11: proc.captureRpcSetPet,
|
||||||
|
0x12: proc.captureRpcSetStartCounter,
|
||||||
|
}
|
||||||
|
return proc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) receiveGameRpcCall(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
v, ok := proc.rpcCallMap[rpc.RPCCallID]
|
||||||
|
if ok {
|
||||||
|
v(net, GameID, rpc)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Unable to parse gamedata rpc call with id of %x\n", rpc.RPCCallID)
|
||||||
|
fmt.Printf("Packet: %v\n", hex.EncodeToString(rpc.UnderlyingHazel.GetUnderlyingPacket().Dump()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcPlayAnimation(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcSyncSettings(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
a := &gamedata.RpcSyncSettings{}
|
||||||
|
a.ReadFromPacket(rpc.UnderlyingHazel.GetUnderlyingPacket())
|
||||||
|
if a.Options.IsDefaults {
|
||||||
|
proc.sus.state.CurrentGame.GameOptions = protocol.NewDefaultGameOptionsData()
|
||||||
|
} else {
|
||||||
|
proc.sus.state.CurrentGame.GameOptions = a.Options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcSetInfected(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcExiled(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcSetName(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
a := &gamedata.RpcSetName{}
|
||||||
|
a.ReadFromPacket(rpc.UnderlyingHazel.GetUnderlyingPacket())
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerNetID[rpc.SenderNetID].PlayerName = a.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcSetColor(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
a := &gamedata.RpcSetColor{}
|
||||||
|
a.ReadFromPacket(rpc.UnderlyingHazel.GetUnderlyingPacket())
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerNetID[rpc.SenderNetID].PlayerColor = a.Color
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcSetHat(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
a := &gamedata.RpcSetHat{}
|
||||||
|
a.ReadFromPacket(rpc.UnderlyingHazel.GetUnderlyingPacket())
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerNetID[rpc.SenderNetID].PlayerHat = a.HatID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcSetSkin(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
a := &gamedata.RpcSetSkin{}
|
||||||
|
a.ReadFromPacket(rpc.UnderlyingHazel.GetUnderlyingPacket())
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerNetID[rpc.SenderNetID].PlayerSkin = a.SkinID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcSetPet(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
a := &gamedata.RpcSetPet{}
|
||||||
|
a.ReadFromPacket(rpc.UnderlyingHazel.GetUnderlyingPacket())
|
||||||
|
proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerNetID[rpc.SenderNetID].PlayerPet = a.PetID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *GameRPCProcessor) captureRpcSetStartCounter(net *protocol.PacketHandler, GameID int32, rpc *gamedata.Rpc) {
|
||||||
|
a := &gamedata.RpcSetStartCounter{}
|
||||||
|
a.ReadFromPacket(rpc.UnderlyingHazel.GetUnderlyingPacket())
|
||||||
|
if proc.sus.state.CurrentGame != nil {
|
||||||
|
proc.sus.state.CurrentGame.StartGameTimer = a.TimeRemaining
|
||||||
|
}
|
||||||
|
}
|
26
go.mod
Normal file
26
go.mod
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
module codehub.onpointcoding.net/sean/go-susapp
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
replace (
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/enum => ./src/enum
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/gamedata => ./src/gamedata
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/innernetobjects => ./src/innernetobjects
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/mapdata => ./src/mapdata
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/packets => ./src/packets
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/protocol => ./src/protocol
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/systemtypes => ./src/systemtypes
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/util => ./src/util
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/enum v1.0.0
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/gamedata v0.0.0-00010101000000-000000000000
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/innernetobjects v0.0.0-00010101000000-000000000000
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/packets v0.0.0-00010101000000-000000000000
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/protocol v1.0.0
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/systemtypes v1.0.0 // indirect
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/util v1.0.0
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/mapdata v1.0.0
|
||||||
|
github.com/gotk3/gotk3 v0.6.1
|
||||||
|
)
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
github.com/gotk3/gotk3 v0.6.1 h1:GJ400a0ecEEWrzjBvzBzH+pB/esEMIGdB9zPSmBdoeo=
|
||||||
|
github.com/gotk3/gotk3 v0.6.1/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
|
80
keyhandler.go
Normal file
80
keyhandler.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"github.com/gotk3/gotk3/gdk"
|
||||||
|
"github.com/gotk3/gotk3/gtk"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KeyInputHandler struct {
|
||||||
|
state *State
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKeyInputHandler(state *State) *KeyInputHandler {
|
||||||
|
return &KeyInputHandler{state}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (input *KeyInputHandler) keyPressEvent(win *gtk.ApplicationWindow, ev *gdk.Event) {
|
||||||
|
keyEvent := gdk.EventKeyNewFromEvent(ev)
|
||||||
|
k := gdk.KeyvalToUpper(keyEvent.KeyVal())
|
||||||
|
if input.state.Screen == enum.SCREEN_TITLE && input.state.IsTypingReady {
|
||||||
|
if k >= gdk.KEY_A && k <= gdk.KEY_Z {
|
||||||
|
input.state.TypedGameID = input.state.TypedGameID + string(gdk.KeyvalToUnicode(k))
|
||||||
|
} else if k == gdk.KEY_BackSpace {
|
||||||
|
if len(input.state.TypedGameID) > 0 {
|
||||||
|
input.state.TypedGameID = input.state.TypedGameID[:len(input.state.TypedGameID)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if input.state.Screen == enum.SCREEN_LOBBY {
|
||||||
|
if k == gdk.KEY_W {
|
||||||
|
input.state.HoldingUp = true
|
||||||
|
}
|
||||||
|
if k == gdk.KEY_A {
|
||||||
|
input.state.HoldingLeft = true
|
||||||
|
}
|
||||||
|
if k == gdk.KEY_S {
|
||||||
|
input.state.HoldingDown = true
|
||||||
|
}
|
||||||
|
if k == gdk.KEY_D {
|
||||||
|
input.state.HoldingRight = true
|
||||||
|
}
|
||||||
|
input.updateMovementDirections()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (input *KeyInputHandler) keyReleaseEvent(win *gtk.ApplicationWindow, ev *gdk.Event) {
|
||||||
|
keyEvent := gdk.EventKeyNewFromEvent(ev)
|
||||||
|
k := gdk.KeyvalToUpper(keyEvent.KeyVal())
|
||||||
|
if input.state.Screen == enum.SCREEN_LOBBY {
|
||||||
|
if k == gdk.KEY_W {
|
||||||
|
input.state.HoldingUp = false
|
||||||
|
}
|
||||||
|
if k == gdk.KEY_A {
|
||||||
|
input.state.HoldingLeft = false
|
||||||
|
}
|
||||||
|
if k == gdk.KEY_S {
|
||||||
|
input.state.HoldingDown = false
|
||||||
|
}
|
||||||
|
if k == gdk.KEY_D {
|
||||||
|
input.state.HoldingRight = false
|
||||||
|
}
|
||||||
|
input.updateMovementDirections()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (input *KeyInputHandler) updateMovementDirections() {
|
||||||
|
input.state.MovementX = 0
|
||||||
|
input.state.MovementY = 0
|
||||||
|
if input.state.HoldingUp {
|
||||||
|
input.state.MovementY--
|
||||||
|
}
|
||||||
|
if input.state.HoldingLeft {
|
||||||
|
input.state.MovementX--
|
||||||
|
}
|
||||||
|
if input.state.HoldingDown {
|
||||||
|
input.state.MovementY++
|
||||||
|
}
|
||||||
|
if input.state.HoldingRight {
|
||||||
|
input.state.MovementX++
|
||||||
|
}
|
||||||
|
}
|
79
mousehandler.go
Normal file
79
mousehandler.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/util"
|
||||||
|
"github.com/gotk3/gotk3/gdk"
|
||||||
|
"github.com/gotk3/gotk3/gtk"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MouseInputHandler struct {
|
||||||
|
state *State
|
||||||
|
renderer *Renderer
|
||||||
|
playGame func()
|
||||||
|
openSettings func()
|
||||||
|
disconnectFromGame func()
|
||||||
|
prevTime int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMouseInputHandler(state *State, renderer *Renderer, playGame func(), openSettings func(), disconnectFromGame func()) *MouseInputHandler {
|
||||||
|
return &MouseInputHandler{state, renderer, playGame, openSettings, disconnectFromGame, time.Now().UnixMilli()}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*func (input *MouseInputHandler) pollingEvent(delta int64) {
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
func (input *MouseInputHandler) motionEvent(da *gtk.DrawingArea, event *gdk.Event) bool {
|
||||||
|
eventMotion := gdk.EventMotionNewFromEvent(event)
|
||||||
|
input.renderer.mouseX, input.renderer.mouseY = eventMotion.MotionVal()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (input *MouseInputHandler) buttonPressEvent(window *gtk.ApplicationWindow, ev *gdk.Event) bool {
|
||||||
|
btn := gdk.EventButtonNewFromEvent(ev)
|
||||||
|
switch btn.Button() {
|
||||||
|
case gdk.BUTTON_PRIMARY:
|
||||||
|
w := input.renderer.w
|
||||||
|
h := input.renderer.h
|
||||||
|
if input.state.Screen == enum.SCREEN_TITLE {
|
||||||
|
if util.CollisionIntersectCenter(input.renderer.mouseX, input.renderer.mouseY, w/2, h/2, 200, 40) {
|
||||||
|
input.playGame()
|
||||||
|
} else if util.CollisionIntersectCenter(input.renderer.mouseX, input.renderer.mouseY, w-40, h-40, 40, 40) {
|
||||||
|
input.openSettings()
|
||||||
|
} else {
|
||||||
|
if util.CollisionIntersectCenter(input.renderer.mouseX, input.renderer.mouseY, w/2, h/2-60, 200, 40) {
|
||||||
|
input.state.IsTypingReady = true
|
||||||
|
} else {
|
||||||
|
input.state.IsTypingReady = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if input.state.Screen == enum.SCREEN_LOBBY {
|
||||||
|
if input.state.IsLobbyMenuOpen {
|
||||||
|
mw := w / 2
|
||||||
|
mh := h / 2
|
||||||
|
overlayBottom := mh + 200
|
||||||
|
if util.CollisionIntersectCenter(input.renderer.mouseX, input.renderer.mouseY, mw, overlayBottom-40, 200, 40) {
|
||||||
|
input.state.IsLobbyMenuOpen = false
|
||||||
|
} else if util.CollisionIntersectCenter(input.renderer.mouseX, input.renderer.mouseY, mw, overlayBottom-100, 200, 40) {
|
||||||
|
input.disconnectFromGame()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if util.CollisionIntersectCenter(input.renderer.mouseX, input.renderer.mouseY, w-40, 40, 40, 40) {
|
||||||
|
input.state.IsLobbyMenuOpen = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if input.state.Screen == enum.SCREEN_ERROR {
|
||||||
|
mw := w / 2
|
||||||
|
mh := h / 2
|
||||||
|
if util.CollisionIntersectCenter(input.renderer.mouseX, input.renderer.mouseY, mw+190, mh-190, 40, 40) {
|
||||||
|
input.state.Screen = enum.SCREEN_TITLE
|
||||||
|
input.state.IsLobbyMenuOpen = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
41
movementprocessor.go
Normal file
41
movementprocessor.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/gamedata"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/innernetobjects"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/packets"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MovementProcessor struct {
|
||||||
|
sus *SusApp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proc *MovementProcessor) Tick(delta int64) {
|
||||||
|
if proc.sus.state.CurrentGame != nil && proc.sus.networkHandler != nil {
|
||||||
|
p := protocol.NewEmptyPacket()
|
||||||
|
cp, ok := proc.sus.state.CurrentGame.PlayerNetObjects.ByPlayerNetID[proc.sus.state.CurrentGame.ClientPlayerNetID]
|
||||||
|
if ok {
|
||||||
|
netId := cp.PlayerNetworkTransform
|
||||||
|
var c0 innernetobjects.InnerNetObject = *proc.sus.state.CurrentGame.NetObjects[netId]
|
||||||
|
a, ok := c0.(*innernetobjects.PlayerNetworkTransform)
|
||||||
|
if ok {
|
||||||
|
a.LastSequenceID++
|
||||||
|
prevVelocityZero := a.TargetVelocity.X == 0 && a.TargetVelocity.Y == 0
|
||||||
|
a.TargetVelocity.X = enum.PLAYER_SPEED * proc.sus.state.CurrentGame.GameOptions.PlayerSpeedModifier * proc.sus.state.MovementX / 2
|
||||||
|
a.TargetVelocity.Y = enum.PLAYER_SPEED * proc.sus.state.CurrentGame.GameOptions.PlayerSpeedModifier * proc.sus.state.MovementY / 2
|
||||||
|
nextVelocityZero := a.TargetVelocity.X == 0 && a.TargetVelocity.Y == 0
|
||||||
|
if !nextVelocityZero || prevVelocityZero != nextVelocityZero {
|
||||||
|
a.TargetPosition.X += a.TargetVelocity.X * (float32(delta) / 1000)
|
||||||
|
a.TargetPosition.Y -= a.TargetVelocity.Y * (float32(delta) / 1000)
|
||||||
|
c0.Write(p, false)
|
||||||
|
var c1 protocol.UpdateComponent = protocol.UpdateComponent{NetID: netId, RawData: p}
|
||||||
|
var c2 packets.GameDataSubpacket = &gamedata.DataH2G{Component: &c1}
|
||||||
|
var c3 protocol.HazelPayload = packets.NewGameDataSingleSubpacket(proc.sus.state.CurrentGame.GameID, &c2)
|
||||||
|
proc.sus.networkHandler.SendNormalPacket([]*protocol.Hazel{protocol.NewHazelFromPayload(&c3)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
172
packetprocessor.go
Normal file
172
packetprocessor.go
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/gamedata"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/innernetobjects"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/packets"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/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){
|
||||||
|
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) 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,
|
||||||
|
OtherClientIDs: make([]uint32, len(a.OtherClientIDs)),
|
||||||
|
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{}
|
||||||
|
for j := 0; j < len(a.OtherClientIDs); j++ {
|
||||||
|
proc.sus.state.CurrentGame.OtherClientIDs[j] = a.OtherClientIDs[j]
|
||||||
|
}
|
||||||
|
proc.sus.state.Screen = enum.SCREEN_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 a.GameID == proc.sus.state.CurrentGame.GameID && a.HostClientID == proc.sus.state.CurrentGame.ClientID {
|
||||||
|
fmt.Println("Host player disconnect and left me in charge")
|
||||||
|
fmt.Println("I can't host a game so I'm disconnecting too")
|
||||||
|
net.SendNormalDisconnectPacket()
|
||||||
|
}
|
||||||
|
}
|
9
project.json
Normal file
9
project.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Package": "melonapp",
|
||||||
|
"Version": "1.0-0",
|
||||||
|
"Section": "base",
|
||||||
|
"Priority": "optional",
|
||||||
|
"Architecture": "amd64",
|
||||||
|
"Maintainer": "MrMelon54 <github@onpointcoding.net>",
|
||||||
|
"Description": "Melon App"
|
||||||
|
}
|
273
renderer.go
Normal file
273
renderer.go
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/innernetobjects"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/util"
|
||||||
|
|
||||||
|
"github.com/gotk3/gotk3/cairo"
|
||||||
|
"github.com/gotk3/gotk3/gtk"
|
||||||
|
"github.com/gotk3/gotk3/pango"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Renderer struct {
|
||||||
|
state *State
|
||||||
|
da *gtk.DrawingArea
|
||||||
|
cr *cairo.Context
|
||||||
|
w float64
|
||||||
|
h float64
|
||||||
|
mouseX float64
|
||||||
|
mouseY float64
|
||||||
|
delta int64
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultRenderFont string = "Noto Sans"
|
||||||
|
|
||||||
|
func NewRenderer(state *State) *Renderer {
|
||||||
|
return &Renderer{state: state}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) Draw(da *gtk.DrawingArea, cr *cairo.Context) {
|
||||||
|
r.delta = time.Now().UnixMilli()
|
||||||
|
r.da = da
|
||||||
|
r.cr = cr
|
||||||
|
allocation := da.GetAllocation()
|
||||||
|
r.w = float64(allocation.GetWidth())
|
||||||
|
r.h = float64(allocation.GetHeight())
|
||||||
|
|
||||||
|
versionText := GetVersionFormatted(r.state.Version)
|
||||||
|
|
||||||
|
// Background
|
||||||
|
r.DrawFilledRectangle(0, 0, r.w, r.h, 0x14181c)
|
||||||
|
|
||||||
|
// Version numbers
|
||||||
|
r.DrawText(10, 10, versionText, "Noto Sans Display", 16, 0xffffff)
|
||||||
|
|
||||||
|
if r.state.Screen == enum.SCREEN_TITLE {
|
||||||
|
colorLen := enum.GetPlayerTotalColors()
|
||||||
|
for i := 0; i < colorLen; i++ {
|
||||||
|
r.DrawFilledRectangle(float64(i)*20+(r.w-float64(colorLen)-float64(colorLen*20))/2, 0, 20, 20, enum.GetPlayerMainColor(i))
|
||||||
|
r.DrawFilledRectangle(float64(i)*20+(r.w-float64(colorLen)-float64(colorLen*20))/2, 20, 20, 20, enum.GetPlayerShadedColor(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
r.DrawButton(r.w-120, 20, 100, 40, r.state.Settings.PlayerName, defaultRenderFont, 16)
|
||||||
|
r.DrawButton(r.w-120, 60, 100, 40, r.state.Settings.ServerAddress, defaultRenderFont, 16)
|
||||||
|
r.DrawButton(r.w-120, 100, 100, 40, strconv.FormatInt(r.state.Settings.ServerPort, 10), defaultRenderFont, 16)
|
||||||
|
|
||||||
|
r.DrawTextInput((r.w-200)/2, (r.h-20)/2-60, 200, 40, r.state.TypedGameID, defaultRenderFont, 16, r.state.IsTypingReady)
|
||||||
|
r.DrawButton((r.w-200)/2, (r.h-20)/2, 200, 40, "Play", defaultRenderFont, 16)
|
||||||
|
r.DrawButton(r.w-60, r.h-60, 40, 40, "⚙", defaultRenderFont, 16)
|
||||||
|
} else if r.state.Screen == enum.SCREEN_WAITING {
|
||||||
|
mw := r.w / 2
|
||||||
|
mh := r.h / 2
|
||||||
|
a := float64(r.delta/10) * (math.Pi / 180)
|
||||||
|
b := a + math.Pi/2
|
||||||
|
c := a + math.Pi
|
||||||
|
d := a + math.Pi*3/2
|
||||||
|
r.DrawFilledRoundedRectangle(mw+50*math.Sin(a)-20, mh+50*math.Cos(a)-20, 40, 40, 1, 20, 0xffffff)
|
||||||
|
r.DrawFilledRoundedRectangle(mw+50*math.Sin(b)-20, mh+50*math.Cos(b)-20, 40, 40, 1, 20, 0xffffff)
|
||||||
|
r.DrawFilledRoundedRectangle(mw+50*math.Sin(c)-20, mh+50*math.Cos(c)-20, 40, 40, 1, 20, 0xffffff)
|
||||||
|
r.DrawFilledRoundedRectangle(mw+50*math.Sin(d)-20, mh+50*math.Cos(d)-20, 40, 40, 1, 20, 0xffffff)
|
||||||
|
} else if r.state.Screen == enum.SCREEN_LOBBY {
|
||||||
|
r.DrawButton((r.w-100)/2, r.h-60, 100, 40, util.CodeFromGameID(r.state.CurrentGame.GameID), defaultRenderFont, 16)
|
||||||
|
r.DrawButton(r.w-60, 20, 40, 40, "⚙", defaultRenderFont, 16)
|
||||||
|
|
||||||
|
if r.state.CurrentGame.GamePrivacy == 1 {
|
||||||
|
r.DrawButton((r.w-100)/2+120, r.h-60, 100, 40, "Public", defaultRenderFont, 16)
|
||||||
|
} else if r.state.CurrentGame.GamePrivacy == 0 {
|
||||||
|
r.DrawButton((r.w-100)/2+120, r.h-60, 100, 40, "Private", defaultRenderFont, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.DrawPlayers()
|
||||||
|
|
||||||
|
if r.state.IsLobbyMenuOpen {
|
||||||
|
mw := r.w / 2
|
||||||
|
mh := r.h / 2
|
||||||
|
overlayBottom := mh + 200
|
||||||
|
|
||||||
|
r.DrawFilledRectangle(0, 0, r.w, r.h, 0x80000000)
|
||||||
|
r.DrawFilledRoundedRectangle(mw-200, mh-200, 400, 400, 1, 20, 0x000000)
|
||||||
|
|
||||||
|
r.DrawButton((r.w-200)/2, overlayBottom-60, 200, 40, "Return to Game", defaultRenderFont, 16)
|
||||||
|
r.DrawButton((r.w-200)/2, overlayBottom-120, 200, 40, "Leave Game", defaultRenderFont, 16)
|
||||||
|
}
|
||||||
|
} else if r.state.Screen == enum.SCREEN_ERROR {
|
||||||
|
mw := r.w / 2
|
||||||
|
mh := r.h / 2
|
||||||
|
r.DrawFilledRoundedRectangle(mw-200, mh-200, 400, 400, 1, 20, 0x000000)
|
||||||
|
|
||||||
|
r.DrawText(mw-190, mh-190, "Disconnected", defaultRenderFont, 16, 0xffffff)
|
||||||
|
r.DrawButton(mw+170, mh-210, 40, 40, "×", defaultRenderFont, 16)
|
||||||
|
if r.state.DisconnectReason == 0xfe {
|
||||||
|
r.DrawWrappedText(mw-190, mh-156, 380, r.state.DisconnectStringReason, defaultRenderFont, 16, 0xffffff)
|
||||||
|
} else {
|
||||||
|
r.DrawWrappedText(mw-190, mh-156, 380, enum.DisconnectMessageText(r.state.DisconnectReason), defaultRenderFont, 16, 0xffffff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) SetRGB(red int, green int, blue int, alpha int) {
|
||||||
|
r.cr.SetSourceRGBA(float64(red)/0xff, float64(green)/0xff, float64(blue)/0xff, 0xff/float64(alpha))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) SetHex(hex int) {
|
||||||
|
r.SetRGB((hex/(256*256))%256, (hex/256)%256, hex%256, (hex/(256*256*256))%256)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawRectangle(x float64, y float64, w float64, h float64, color int) {
|
||||||
|
r.SetHex(color)
|
||||||
|
r.cr.Rectangle(x, y, w, h)
|
||||||
|
r.cr.Stroke()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawFilledRectangle(x float64, y float64, w float64, h float64, color int) {
|
||||||
|
r.SetHex(color)
|
||||||
|
r.cr.Rectangle(x, y, w, h)
|
||||||
|
r.cr.Fill()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawBorderedRectangle(x float64, y float64, w float64, h float64, color int, border int) {
|
||||||
|
r.DrawFilledRectangle(x, y, w, h, color)
|
||||||
|
r.DrawRectangle(x, y, w, h, border)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawRoundedRectangle(x float64, y float64, w float64, h float64, aspect float64, corner_radius float64, color int) {
|
||||||
|
a := corner_radius / aspect
|
||||||
|
d := math.Pi / 180
|
||||||
|
r.cr.NewPath()
|
||||||
|
r.cr.Arc(x+w-a, y+a, a, -90*d, 0*d)
|
||||||
|
r.cr.Arc(x+w-a, y+h-a, a, 0*d, 90*d)
|
||||||
|
r.cr.Arc(x+a, y+h-a, a, 90*d, 180*d)
|
||||||
|
r.cr.Arc(x+a, y+a, a, 180*d, 270*d)
|
||||||
|
r.cr.ClosePath()
|
||||||
|
r.SetHex(color)
|
||||||
|
r.cr.Stroke()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawFilledRoundedRectangle(x float64, y float64, w float64, h float64, aspect float64, corner_radius float64, color int) {
|
||||||
|
a := corner_radius / aspect
|
||||||
|
d := math.Pi / 180
|
||||||
|
r.cr.NewPath()
|
||||||
|
r.cr.Arc(x+w-a, y+a, a, -90*d, 0*d)
|
||||||
|
r.cr.Arc(x+w-a, y+h-a, a, 0*d, 90*d)
|
||||||
|
r.cr.Arc(x+a, y+h-a, a, 90*d, 180*d)
|
||||||
|
r.cr.Arc(x+a, y+a, a, 180*d, 270*d)
|
||||||
|
r.cr.ClosePath()
|
||||||
|
r.SetHex(color)
|
||||||
|
r.cr.FillPreserve()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawBorderedRoundedRectangle(x float64, y float64, w float64, h float64, aspect float64, corner_radius float64, color int, border int) {
|
||||||
|
a := corner_radius / aspect
|
||||||
|
d := math.Pi / 180
|
||||||
|
r.cr.NewPath()
|
||||||
|
r.cr.Arc(x+w-a, y+a, a, -90*d, 0*d)
|
||||||
|
r.cr.Arc(x+w-a, y+h-a, a, 0*d, 90*d)
|
||||||
|
r.cr.Arc(x+a, y+h-a, a, 90*d, 180*d)
|
||||||
|
r.cr.Arc(x+a, y+a, a, 180*d, 270*d)
|
||||||
|
r.cr.ClosePath()
|
||||||
|
r.SetHex(color)
|
||||||
|
r.cr.FillPreserve()
|
||||||
|
r.SetHex(border)
|
||||||
|
r.cr.Stroke()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawText(x float64, y float64, text string, fontFamily string, fontSize float64, color int) {
|
||||||
|
layout := pango.CairoCreateLayout(r.cr)
|
||||||
|
font := pango.FontDescriptionFromString("sans normal 16")
|
||||||
|
font.SetFamily(fontFamily)
|
||||||
|
|
||||||
|
layout.SetFontDescription(font)
|
||||||
|
layout.SetText(text, len(text))
|
||||||
|
|
||||||
|
r.SetHex(color)
|
||||||
|
r.cr.MoveTo(x, y)
|
||||||
|
pango.CairoUpdateLayout(r.cr, layout)
|
||||||
|
pango.CairoShowLayout(r.cr, layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawWrappedText(x float64, y float64, w float64, text string, fontFamily string, fontSize float64, color int) {
|
||||||
|
layout := pango.CairoCreateLayout(r.cr)
|
||||||
|
layout.SetWidth(int(w) * pango.SCALE)
|
||||||
|
font := pango.FontDescriptionFromString("sans normal 16")
|
||||||
|
font.SetFamily(fontFamily)
|
||||||
|
|
||||||
|
layout.SetFontDescription(font)
|
||||||
|
layout.SetText(text, len(text))
|
||||||
|
|
||||||
|
r.SetHex(color)
|
||||||
|
r.cr.MoveTo(x, y)
|
||||||
|
pango.CairoUpdateLayout(r.cr, layout)
|
||||||
|
pango.CairoShowLayout(r.cr, layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawButton(x float64, y float64, w float64, h float64, text string, fontFamily string, fontSize float64) {
|
||||||
|
r.DrawFilledRoundedRectangle(x, y, w-4, h-4, w/h, 10, 0x000000)
|
||||||
|
|
||||||
|
if r.mouseX > x && r.mouseX < x+w && r.mouseY > y && r.mouseY < y+h {
|
||||||
|
r.DrawRoundedRectangle(x, y, w-4, h-4, w/h, 10, 0x00ff00)
|
||||||
|
} else {
|
||||||
|
r.DrawRoundedRectangle(x, y, w-4, h-4, w/h, 10, 0xffffff)
|
||||||
|
}
|
||||||
|
|
||||||
|
layout := pango.CairoCreateLayout(r.cr)
|
||||||
|
font := pango.FontDescriptionFromString("sans normal 16")
|
||||||
|
font.SetFamily(fontFamily)
|
||||||
|
|
||||||
|
layout.SetFontDescription(font)
|
||||||
|
layout.SetText(text, len(text))
|
||||||
|
|
||||||
|
textWidth, textHeight := layout.GetSize()
|
||||||
|
textWidth /= pango.SCALE
|
||||||
|
textHeight /= pango.SCALE
|
||||||
|
|
||||||
|
r.SetHex(0xffffff)
|
||||||
|
r.cr.MoveTo(x+(w-4-float64(textWidth))/2, y+(h-4-float64(textHeight))/2)
|
||||||
|
pango.CairoUpdateLayout(r.cr, layout)
|
||||||
|
pango.CairoShowLayout(r.cr, layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawTextInput(x float64, y float64, w float64, h float64, text string, fontFamily string, fontSize float64, inFocus bool) {
|
||||||
|
if r.mouseX > x && r.mouseX < x+w && r.mouseY > y && r.mouseY < y+h {
|
||||||
|
r.DrawFilledRectangle(x, y+h-6, w-4, 2, 0x00ffff)
|
||||||
|
} else {
|
||||||
|
r.DrawFilledRectangle(x, y+h-6, w-4, 2, 0xffffff)
|
||||||
|
}
|
||||||
|
|
||||||
|
layout := pango.CairoCreateLayout(r.cr)
|
||||||
|
font := pango.FontDescriptionFromString("sans normal 16")
|
||||||
|
font.SetFamily(fontFamily)
|
||||||
|
|
||||||
|
layout.SetFontDescription(font)
|
||||||
|
layout.SetText(text, len(text))
|
||||||
|
|
||||||
|
textWidth, textHeight := layout.GetSize()
|
||||||
|
textWidth /= pango.SCALE
|
||||||
|
textHeight /= pango.SCALE
|
||||||
|
|
||||||
|
r.SetHex(0xffffff)
|
||||||
|
r.cr.MoveTo(x+(w-float64(textWidth))/2, y+(h-12-float64(textHeight))/2)
|
||||||
|
pango.CairoUpdateLayout(r.cr, layout)
|
||||||
|
pango.CairoShowLayout(r.cr, layout)
|
||||||
|
|
||||||
|
if inFocus && r.delta%1600 < 800 {
|
||||||
|
r.DrawFilledRectangle(x+(w+float64(textWidth))/2, y+4, 2, 20, 0xffffff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) DrawPlayers() {
|
||||||
|
for _, item := range r.state.CurrentGame.PlayerNetObjects.ByPlayerClientID {
|
||||||
|
var t innernetobjects.InnerNetObject = *r.state.CurrentGame.NetObjects[item.PlayerNetworkTransform]
|
||||||
|
a, ok := t.(*innernetobjects.PlayerNetworkTransform)
|
||||||
|
if ok {
|
||||||
|
x := r.w/2 + float64(a.TargetPosition.X)*50
|
||||||
|
y := r.h/2 - float64(a.TargetPosition.Y)*50
|
||||||
|
r.DrawFilledRectangle(float64(x-5), float64(y-5), 10, 10, enum.GetPlayerMainColor(int(item.PlayerColor)))
|
||||||
|
r.DrawText(x, y, strconv.FormatFloat(float64(a.TargetPosition.X), 'e', 4, 64)+strconv.FormatFloat(float64(a.TargetPosition.Y), 'e', 4, 64), defaultRenderFont, 10, 0xffffff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
settings.go
Normal file
37
settings.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SettingsJSON struct {
|
||||||
|
PlayerName string `json:"PlayerName"`
|
||||||
|
PlayerColor byte `json:"PlayerColor"`
|
||||||
|
ServerAddress string `json:"ServerAddress"`
|
||||||
|
ServerPort int64 `json:"ServerPort"`
|
||||||
|
Language uint32 `json:"Language"`
|
||||||
|
QuickChatMode byte `json:"QuickChatMode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalSettings(data []byte) (SettingsJSON, error) {
|
||||||
|
var r SettingsJSON
|
||||||
|
err := json.Unmarshal(data, &r)
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SettingsJSON) Marshal() ([]byte, error) {
|
||||||
|
return json.Marshal(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDefaultSettingsJSON() SettingsJSON {
|
||||||
|
return SettingsJSON{
|
||||||
|
PlayerName: "Player 1",
|
||||||
|
PlayerColor: 0,
|
||||||
|
ServerAddress: "localhost",
|
||||||
|
ServerPort: 22023,
|
||||||
|
Language: enum.GAMEKEYWORD_ALL,
|
||||||
|
QuickChatMode: enum.QUICK_CHAT_ONLY,
|
||||||
|
}
|
||||||
|
}
|
225
settingswindow.go
Normal file
225
settingswindow.go
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"github.com/gotk3/gotk3/glib"
|
||||||
|
"github.com/gotk3/gotk3/gtk"
|
||||||
|
)
|
||||||
|
|
||||||
|
var langaugeIdxMap = []int{
|
||||||
|
enum.GAMEKEYWORD_ALL,
|
||||||
|
enum.GAMEKEYWORD_OTHER,
|
||||||
|
enum.GAMEKEYWORD_SPANISH,
|
||||||
|
enum.GAMEKEYWORD_KOREAN,
|
||||||
|
enum.GAMEKEYWORD_RUSSIAN,
|
||||||
|
enum.GAMEKEYWORD_PORTUGUESE,
|
||||||
|
enum.GAMEKEYWORD_ARABIC,
|
||||||
|
enum.GAMEKEYWORD_FILIPINO,
|
||||||
|
enum.GAMEKEYWORD_POLISH,
|
||||||
|
enum.GAMEKEYWORD_ENGLISH,
|
||||||
|
enum.GAMEKEYWORD_JAPANESE,
|
||||||
|
}
|
||||||
|
var quickChatIdxMap = []int{
|
||||||
|
enum.FREE_CHAT_OR_QUICK_CHAT,
|
||||||
|
enum.QUICK_CHAT_ONLY,
|
||||||
|
}
|
||||||
|
|
||||||
|
func openSettingsWindow(application *gtk.Application, mainWindow *gtk.ApplicationWindow, state *State) {
|
||||||
|
optWindow, err := gtk.ApplicationWindowNew(application)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Could not create application window.", err)
|
||||||
|
}
|
||||||
|
// Set ApplicationWindow Properties
|
||||||
|
optWindow.SetTitle("Sus App > Settings")
|
||||||
|
optWindow.SetDefaultSize(350, 350)
|
||||||
|
|
||||||
|
layout, _ := gtk.LayoutNew(nil, nil)
|
||||||
|
optWindow.Add(layout)
|
||||||
|
|
||||||
|
_, usernameEntry := addTextWidget(layout, 8, "Username:", state.Settings.PlayerName)
|
||||||
|
_, colorEntry := addColorWidget(layout, 50, "Color:", state.Settings.PlayerColor)
|
||||||
|
_, serverEntry := addTextWidget(layout, 92, "Address:", state.Settings.ServerAddress)
|
||||||
|
_, portEntry := addTextWidget(layout, 134, "Port:", strconv.FormatInt(state.Settings.ServerPort, 10))
|
||||||
|
_, languageEntry := addLanguageWidget(layout, 176, "Language:", state.Settings.Language)
|
||||||
|
_, quickChatEntry := addQuickChatWidget(layout, 218, "Quick Chat:", state.Settings.QuickChatMode)
|
||||||
|
|
||||||
|
applyBtn, _ := gtk.ButtonNewWithLabel("Apply")
|
||||||
|
layout.Put(applyBtn, 8, 218)
|
||||||
|
applyBtn.SetSizeRequest(334, 34)
|
||||||
|
applyBtn.Connect("clicked", func(b *gtk.Button) {
|
||||||
|
//
|
||||||
|
// Username
|
||||||
|
//
|
||||||
|
a1, err := usernameEntry.GetText()
|
||||||
|
if err == nil {
|
||||||
|
state.Settings.PlayerName = a1
|
||||||
|
} else {
|
||||||
|
showSettingsErrorDialog(optWindow, "Failed to get new player name")
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Server
|
||||||
|
//
|
||||||
|
a2, err := serverEntry.GetText()
|
||||||
|
if err == nil {
|
||||||
|
state.Settings.ServerAddress = a2
|
||||||
|
} else {
|
||||||
|
showSettingsErrorDialog(optWindow, "Failed to get new server address")
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Port
|
||||||
|
//
|
||||||
|
a3, err := portEntry.GetText()
|
||||||
|
if err == nil {
|
||||||
|
b3, err := strconv.ParseInt(a3, 10, 64)
|
||||||
|
if err == nil {
|
||||||
|
state.Settings.ServerPort = b3
|
||||||
|
} else {
|
||||||
|
showSettingsErrorDialog(optWindow, fmt.Sprintf("Failed to parse port %v as it is not a valid integer", a3))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showSettingsErrorDialog(optWindow, "Failed to get new port")
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Language
|
||||||
|
//
|
||||||
|
a4 := languageEntry.GetActive()
|
||||||
|
state.Settings.Language = uint32(langaugeIdxMap[a4])
|
||||||
|
|
||||||
|
//
|
||||||
|
// Quick chat mode
|
||||||
|
//
|
||||||
|
a5 := quickChatEntry.GetActive()
|
||||||
|
state.Settings.QuickChatMode = byte(quickChatIdxMap[a5])
|
||||||
|
|
||||||
|
//
|
||||||
|
// Color
|
||||||
|
//
|
||||||
|
a6 := colorEntry.GetActive()
|
||||||
|
state.Settings.PlayerColor = byte(a6)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save
|
||||||
|
//
|
||||||
|
state.SaveSettings()
|
||||||
|
})
|
||||||
|
|
||||||
|
optWindow.ShowAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
func showSettingsErrorDialog(optWindow *gtk.ApplicationWindow, msg string) {
|
||||||
|
mDialog := gtk.MessageDialogNew(optWindow, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, msg)
|
||||||
|
mDialog.SetTitle("Sus App Error")
|
||||||
|
mDialog.Run()
|
||||||
|
mDialog.Destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
func addTextWidget(layout *gtk.Layout, y int, txt string, orig string) (*gtk.Label, *gtk.Entry) {
|
||||||
|
label, _ := gtk.LabelNew(txt)
|
||||||
|
layout.Put(label, 8, y+6)
|
||||||
|
|
||||||
|
entry, _ := gtk.EntryNew()
|
||||||
|
layout.Put(entry, 100, y)
|
||||||
|
entry.SetSizeRequest(242, 34)
|
||||||
|
entry.SetText(orig)
|
||||||
|
|
||||||
|
return label, entry
|
||||||
|
}
|
||||||
|
|
||||||
|
func addLanguageWidget(layout *gtk.Layout, y int, txt string, orig uint32) (*gtk.Label, *gtk.ComboBox) {
|
||||||
|
var origIter *gtk.TreeIter
|
||||||
|
langStore, _ := gtk.ListStoreNew(glib.TYPE_UINT, glib.TYPE_STRING)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_ALL, "All", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_OTHER, "Other", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_SPANISH, "Spanish", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_KOREAN, "Korean", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_RUSSIAN, "Russian", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_PORTUGUESE, "Portuguese", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_ARABIC, "Arabic", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_FILIPINO, "Filipino", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_POLISH, "Polish", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_ENGLISH, "English", orig, origIter)
|
||||||
|
_, origIter = addRow(langStore, enum.GAMEKEYWORD_JAPANESE, "Japanese", orig, origIter)
|
||||||
|
|
||||||
|
label, _ := gtk.LabelNew(txt)
|
||||||
|
layout.Put(label, 8, y+6)
|
||||||
|
|
||||||
|
combo, _ := gtk.ComboBoxNewWithModel(langStore)
|
||||||
|
rendererText, _ := gtk.CellRendererTextNew()
|
||||||
|
combo.PackStart(rendererText, true)
|
||||||
|
combo.AddAttribute(rendererText, "text", 1)
|
||||||
|
combo.SetSizeRequest(242, 34)
|
||||||
|
combo.SetActiveIter(origIter)
|
||||||
|
layout.Put(combo, 100, y)
|
||||||
|
|
||||||
|
return label, combo
|
||||||
|
}
|
||||||
|
|
||||||
|
func addQuickChatWidget(layout *gtk.Layout, y int, txt string, orig byte) (*gtk.Label, *gtk.ComboBox) {
|
||||||
|
var origIter *gtk.TreeIter
|
||||||
|
modeStore, _ := gtk.ListStoreNew(glib.TYPE_UINT, glib.TYPE_STRING)
|
||||||
|
_, origIter = addRow(modeStore, enum.FREE_CHAT_OR_QUICK_CHAT, "Free Chat or Quick Chat", uint32(orig), origIter)
|
||||||
|
_, origIter = addRow(modeStore, enum.QUICK_CHAT_ONLY, "Quick Chat Only", uint32(orig), origIter)
|
||||||
|
|
||||||
|
label, _ := gtk.LabelNew(txt)
|
||||||
|
layout.Put(label, 8, y+6)
|
||||||
|
|
||||||
|
combo, _ := gtk.ComboBoxNewWithModel(modeStore)
|
||||||
|
rendererText, _ := gtk.CellRendererTextNew()
|
||||||
|
combo.PackStart(rendererText, true)
|
||||||
|
combo.AddAttribute(rendererText, "text", 1)
|
||||||
|
combo.SetSizeRequest(242, 34)
|
||||||
|
combo.SetActiveIter(origIter)
|
||||||
|
layout.Put(combo, 100, y)
|
||||||
|
|
||||||
|
return label, combo
|
||||||
|
}
|
||||||
|
|
||||||
|
func addColorWidget(layout *gtk.Layout, y int, txt string, orig byte) (*gtk.Label, *gtk.ComboBox) {
|
||||||
|
var origIter *gtk.TreeIter
|
||||||
|
modeStore, _ := gtk.ListStoreNew(glib.TYPE_UINT, glib.TYPE_STRING)
|
||||||
|
|
||||||
|
for i := 0; i < enum.GetPlayerTotalColors(); i++ {
|
||||||
|
_, origIter = addRow(modeStore, uint32(i), enum.GetPlayerColorName(i), uint32(orig), origIter)
|
||||||
|
}
|
||||||
|
|
||||||
|
label, _ := gtk.LabelNew(txt)
|
||||||
|
layout.Put(label, 8, y+6)
|
||||||
|
|
||||||
|
combo, _ := gtk.ComboBoxNewWithModel(modeStore)
|
||||||
|
rendererText, _ := gtk.CellRendererTextNew()
|
||||||
|
combo.PackStart(rendererText, true)
|
||||||
|
combo.AddAttribute(rendererText, "text", 1)
|
||||||
|
combo.SetSizeRequest(242, 34)
|
||||||
|
combo.SetActiveIter(origIter)
|
||||||
|
layout.Put(combo, 100, y)
|
||||||
|
|
||||||
|
return label, combo
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append a row to the list store for the tree view
|
||||||
|
func addRow(listStore *gtk.ListStore, id uint32, feature string, origId uint32, origIter *gtk.TreeIter) (*gtk.TreeIter, *gtk.TreeIter) {
|
||||||
|
// Get an iterator for a new row at the end of the list store
|
||||||
|
iter := listStore.Append()
|
||||||
|
|
||||||
|
if id == origId {
|
||||||
|
origIter = iter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the contents of the list store row that the iterator represents
|
||||||
|
err := listStore.Set(iter,
|
||||||
|
[]int{0, 1},
|
||||||
|
[]interface{}{id, feature})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Unable to add row:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return iter, origIter
|
||||||
|
}
|
61
src/enum/disconnectreason.go
Normal file
61
src/enum/disconnectreason.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
DISCONNECT_EXIT_GAME = 0
|
||||||
|
DISCONNECT_GAME_FULL = 1
|
||||||
|
DISCONNECT_GAME_STARTED = 2
|
||||||
|
DISCONNECT_GAME_NOT_FOUND = 3
|
||||||
|
DISCONNECT_INCORRECT_VERSION = 5
|
||||||
|
DISCONNECT_BANNED = 6
|
||||||
|
DISCONNECT_KICKED = 7
|
||||||
|
DISCONNECT_CUSTOM = 8
|
||||||
|
DISCONNECT_INVALID_NAME = 9
|
||||||
|
DISCONNECT_HACKING = 10
|
||||||
|
DISCONNECT_NOT_AUTHORIZED = 11
|
||||||
|
DISCONNECT_DESTROY = 16
|
||||||
|
DISCONNECT_ERROR = 17
|
||||||
|
DISCONNECT_INCORRECT_GAME = 18
|
||||||
|
DISCONNECT_SERVER_REQUEST = 19
|
||||||
|
DISCONNECT_SERVER_FULL = 20
|
||||||
|
DISCONNECT_FOCUS_LOST_BACKGROUND = 207
|
||||||
|
)
|
||||||
|
|
||||||
|
func DisconnectMessageText(reason byte) string {
|
||||||
|
switch reason {
|
||||||
|
case DISCONNECT_EXIT_GAME:
|
||||||
|
return "Exit game"
|
||||||
|
case DISCONNECT_GAME_FULL:
|
||||||
|
return "Game full"
|
||||||
|
case DISCONNECT_GAME_STARTED:
|
||||||
|
return "Game started"
|
||||||
|
case DISCONNECT_GAME_NOT_FOUND:
|
||||||
|
return "Game not found"
|
||||||
|
case DISCONNECT_INCORRECT_VERSION:
|
||||||
|
return "Incorrect version"
|
||||||
|
case DISCONNECT_BANNED:
|
||||||
|
return "Banned"
|
||||||
|
case DISCONNECT_KICKED:
|
||||||
|
return "Kicked"
|
||||||
|
case DISCONNECT_CUSTOM:
|
||||||
|
return "Custom"
|
||||||
|
case DISCONNECT_INVALID_NAME:
|
||||||
|
return "Invalid name"
|
||||||
|
case DISCONNECT_HACKING:
|
||||||
|
return "Hacking"
|
||||||
|
case DISCONNECT_NOT_AUTHORIZED:
|
||||||
|
return "Not authorized"
|
||||||
|
case DISCONNECT_DESTROY:
|
||||||
|
return "Destroy"
|
||||||
|
case DISCONNECT_ERROR:
|
||||||
|
return "Error"
|
||||||
|
case DISCONNECT_INCORRECT_GAME:
|
||||||
|
return "Incorrect game"
|
||||||
|
case DISCONNECT_SERVER_REQUEST:
|
||||||
|
return "Server request"
|
||||||
|
case DISCONNECT_SERVER_FULL:
|
||||||
|
return "Server full"
|
||||||
|
case DISCONNECT_FOCUS_LOST_BACKGROUND:
|
||||||
|
return "Focus lost background"
|
||||||
|
}
|
||||||
|
return "Lost connection"
|
||||||
|
}
|
15
src/enum/gamekeyword.go
Normal file
15
src/enum/gamekeyword.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
GAMEKEYWORD_ALL = 0
|
||||||
|
GAMEKEYWORD_OTHER = 1
|
||||||
|
GAMEKEYWORD_SPANISH = 2
|
||||||
|
GAMEKEYWORD_KOREAN = 4
|
||||||
|
GAMEKEYWORD_RUSSIAN = 8
|
||||||
|
GAMEKEYWORD_PORTUGUESE = 16
|
||||||
|
GAMEKEYWORD_ARABIC = 32
|
||||||
|
GAMEKEYWORD_FILIPINO = 64
|
||||||
|
GAMEKEYWORD_POLISH = 128
|
||||||
|
GAMEKEYWORD_ENGLISH = 256
|
||||||
|
GAMEKEYWORD_JAPANESE = 512
|
||||||
|
)
|
11
src/enum/gameoverreason.go
Normal file
11
src/enum/gameoverreason.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
GAMEOVERREASON_CREWMATES_BY_VOTE = 0
|
||||||
|
GAMEOVERREASON_CREWMATES_BY_TASK = 1
|
||||||
|
GAMEOVERREASON_IMPOSTORS_BY_VOTE = 2
|
||||||
|
GAMEOVERREASON_IMPOSTORS_BY_KILL = 3
|
||||||
|
GAMEOVERREASON_IMPOSTORS_BY_SABOTAGE = 4
|
||||||
|
GAMEOVERREASON_IMPOSTOR_DISCONNECT = 5
|
||||||
|
GAMEOVERREASON_CREWMATE_DISCONNECT = 6
|
||||||
|
)
|
8
src/enum/gamestate.go
Normal file
8
src/enum/gamestate.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
GAMESTATE_NOT_STARTED = 0
|
||||||
|
GAMESTATE_STARTED = 1
|
||||||
|
GAMESTATE_ENDED = 2
|
||||||
|
GAMESTATE_DESTROYED = 3
|
||||||
|
)
|
3
src/enum/go.mod
Normal file
3
src/enum/go.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module codehub.onpointcoding.net/sean/go-susapp/enum
|
||||||
|
|
||||||
|
go 1.17
|
119
src/enum/hat.go
Normal file
119
src/enum/hat.go
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
HAT_NONE = 0
|
||||||
|
HAT_ASTRONAUT = 1
|
||||||
|
HAT_BASEBALL_CAP = 2
|
||||||
|
HAT_BRAIN_SLUG = 3
|
||||||
|
HAT_BUSH_HAT = 4
|
||||||
|
HAT_CAPTAIN_HAT = 5
|
||||||
|
HAT_DOUBLE_TOP_HAT = 6
|
||||||
|
HAT_FLOWERPOT = 7
|
||||||
|
HAT_GOGGLES = 8
|
||||||
|
HAT_HARD_HAT = 9
|
||||||
|
HAT_MILITARY_HAT = 10
|
||||||
|
HAT_PAPER_HAT = 11
|
||||||
|
HAT_PARTY_HAT = 12
|
||||||
|
HAT_POLICE_HAT = 13
|
||||||
|
HAT_STETHOSCOPE = 14
|
||||||
|
HAT_TOP_HAT = 15
|
||||||
|
HAT_TOWEL_WIZARD = 16
|
||||||
|
HAT_USHANKA = 17
|
||||||
|
HAT_VIKING = 18
|
||||||
|
HAT_WALL_GUARD_CAP = 19
|
||||||
|
HAT_SNOWMAN = 20
|
||||||
|
HAT_REINDEER_ANTLERS = 21
|
||||||
|
HAT_CHRISTMAS_LIGHTS = 22
|
||||||
|
HAT_SANTA_HAT = 23
|
||||||
|
HAT_CHRISTMAS_TREE = 24
|
||||||
|
HAT_CHRISTMAS_PRESENT = 25
|
||||||
|
HAT_CANDY_CANES = 26
|
||||||
|
HAT_ELF_HAT = 27
|
||||||
|
HAT_NEW_YEARS_2018 = 28
|
||||||
|
HAT_WHITE_HAT = 29
|
||||||
|
HAT_CROWN = 30
|
||||||
|
HAT_EYEBROWS = 31
|
||||||
|
HAT_HALO = 32
|
||||||
|
HAT_HERO_CAP = 33
|
||||||
|
HAT_PIP_CAP = 34
|
||||||
|
HAT_PLUNGER = 35
|
||||||
|
HAT_SCUBA_MASK = 36
|
||||||
|
HAT_HENRY_STICKMIN = 37
|
||||||
|
HAT_STRAW_HAT = 38
|
||||||
|
HAT_TEN_GALLON_HAT = 39
|
||||||
|
HAT_THIRD_EYE = 40
|
||||||
|
HAT_TOILET_PAPER = 41
|
||||||
|
HAT_TOPPAT_CLAN_LEADER = 42
|
||||||
|
HAT_BLACK_FEDORA = 43
|
||||||
|
HAT_SKI_GOGGLES = 44
|
||||||
|
HAT_HEARING_PROTECTION = 45
|
||||||
|
HAT_HAZMAT_MASK = 46
|
||||||
|
HAT_FACE_MASK = 47
|
||||||
|
HAT_MIRA_SECURITY_CAP = 48
|
||||||
|
HAT_SAFARI_HAT = 49
|
||||||
|
HAT_BANANA = 50
|
||||||
|
HAT_BEANIE = 51
|
||||||
|
HAT_BEAR_EARS = 52
|
||||||
|
HAT_CHEESE = 53
|
||||||
|
HAT_CHERRY = 54
|
||||||
|
HAT_EGG = 55
|
||||||
|
HAT_GREEN_FEDORA = 56
|
||||||
|
HAT_FLAMINGO = 57
|
||||||
|
HAT_FLOWER_PIN = 58
|
||||||
|
HAT_KNIGHT_HELMET = 59
|
||||||
|
HAT_PLANT = 60
|
||||||
|
HAT_BAT_EYES = 61
|
||||||
|
HAT_BAT_WINGS = 62
|
||||||
|
HAT_HORNS = 63
|
||||||
|
HAT_MOHAWK = 64
|
||||||
|
HAT_PUMPKIN = 65
|
||||||
|
HAT_SCARY_PAPER_BAG = 66
|
||||||
|
HAT_WITCH_HAT = 67
|
||||||
|
HAT_WOLF_EARS = 68
|
||||||
|
HAT_PIRATE_HAT = 69
|
||||||
|
HAT_PLAGUE_DOCTOR = 70
|
||||||
|
HAT_MACHETE = 71
|
||||||
|
HAT_HOCKEY_MASK = 72
|
||||||
|
HAT_MINER_HELMET = 73
|
||||||
|
HAT_WINTER_CAP = 74
|
||||||
|
HAT_ARCHAEOLOGIST_HAT = 75
|
||||||
|
HAT_ANTENNA = 76
|
||||||
|
HAT_BALLOON = 77
|
||||||
|
HAT_BIRD_NEST = 78
|
||||||
|
HAT_BLACK_BELT = 79
|
||||||
|
HAT_CAUTION_SIGN = 80
|
||||||
|
HAT_CHEF_HAT = 81
|
||||||
|
HAT_COP_HAT = 82
|
||||||
|
HAT_DO_RAG = 83
|
||||||
|
HAT_DUM_STICKER = 84
|
||||||
|
HAT_FEZ = 85
|
||||||
|
HAT_GENERAL_HAT = 86
|
||||||
|
HAT_POMPADOUR_HAIR = 87
|
||||||
|
HAT_HUNTER_HAT = 88
|
||||||
|
HAT_JUNGLE_HAT = 89
|
||||||
|
HAT_MINI_CREWMATE = 90
|
||||||
|
HAT_NINJA_MASK = 91
|
||||||
|
HAT_RAM_HORNS = 92
|
||||||
|
HAT_MINI_CREWMATE_SNOWMAN = 93
|
||||||
|
HAT_GEOFF_KEIGHLEY_MASK = 94
|
||||||
|
HAT_DAVE_PANPA_CAP = 95
|
||||||
|
HAT_ELLIE_ROSE_HAIR = 96
|
||||||
|
HAT_SVEN_SVENSSON_HAT = 97
|
||||||
|
HAT_BURT_CURTIS_HAT = 98
|
||||||
|
HAT_ELLRY_MOHAWK = 99
|
||||||
|
HAT_THOMAS_CHESTERSHIRE_MONOCLES = 100
|
||||||
|
HAT_WIZARD_HAT = 101
|
||||||
|
HAT_FREDRICK_MUENSTER_HAT = 102
|
||||||
|
HAT_MR_MACBETH_HAT = 103
|
||||||
|
HAT_TOPPAT_HENRY_STICKMIN_HAT = 104
|
||||||
|
HAT_TOPPAT_ELLIE_ROSE_HAT = 105
|
||||||
|
HAT_GEOFFREY_PLUMB_HAT = 106
|
||||||
|
HAT_ANGRY_EYEBROWS = 107
|
||||||
|
HAT_CHOCOLATE_ICE_CREAM = 108
|
||||||
|
HAT_HEART_PIN = 109
|
||||||
|
HAT_PONYTAIL = 110
|
||||||
|
HAT_RUBBER_GLOVE = 111
|
||||||
|
HAT_UNICORN_HORN = 112
|
||||||
|
HAT_ZIPPER = 113
|
||||||
|
HAT_RIGHT_HAND_MAN_HAT = 114
|
||||||
|
)
|
16
src/enum/killdistance.go
Normal file
16
src/enum/killdistance.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
KILLDISTANCE_SHORT = 0
|
||||||
|
KILLDISTANCE_NORMAL = 1
|
||||||
|
KILLDISTANCE_LONG = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
var distanceMap = []float64{1, 1.8, 2.5}
|
||||||
|
|
||||||
|
func GetKillDistanceMagnitude(a int) float64 {
|
||||||
|
if a < 0 || a > len(distanceMap) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return distanceMap[a]
|
||||||
|
}
|
7
src/enum/limbostate.go
Normal file
7
src/enum/limbostate.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
LIMBOSTATE_PRE_SPAWN = 0
|
||||||
|
LIMBOSTATE_NOT_LIMBO = 1
|
||||||
|
LIMBOSTATE_WAITING_FOR_HOST = 2
|
||||||
|
)
|
20
src/enum/map.go
Normal file
20
src/enum/map.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
MAP_THE_SKELD = 0
|
||||||
|
MAP_MIRA_HQ = 1
|
||||||
|
MAP_POLUS = 2
|
||||||
|
MAP_THE_AIRSHIP = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
func MapBitfield(a []int) byte {
|
||||||
|
var b byte = 0
|
||||||
|
for i := 0; i < len(a); i++ {
|
||||||
|
b |= 1 << a[i]
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func BitfieldHasMap(b byte, a int) bool {
|
||||||
|
return b&(1<<a) != 0
|
||||||
|
}
|
16
src/enum/pet.go
Normal file
16
src/enum/pet.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
PET_NONE = 0
|
||||||
|
PET_ALIEN = 1
|
||||||
|
PET_MINI_CREWMATE = 2
|
||||||
|
PET_DOG = 3
|
||||||
|
PET_HENRY_STICKMIN = 4
|
||||||
|
PET_HAMSTER = 5
|
||||||
|
PET_ROBOT = 6
|
||||||
|
PET_UFO = 7
|
||||||
|
PET_ELLIE_ROSE = 8
|
||||||
|
PET_SQUIG = 9
|
||||||
|
PET_BEDCRAB = 10
|
||||||
|
PET_GLITCH = 11
|
||||||
|
)
|
24
src/enum/platform.go
Normal file
24
src/enum/platform.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
PLATFORM_OSXEditor = 0
|
||||||
|
PLATFORM_OSXPlayer = 1
|
||||||
|
PLATFORM_WindowsPlayer = 2
|
||||||
|
PLATFORM_WindowsEditor = 7
|
||||||
|
PLATFORM_IPhonePlayer = 8
|
||||||
|
PLATFORM_Android = 11
|
||||||
|
PLATFORM_LinuxPlayer = 13
|
||||||
|
PLATFORM_LinuxEditor = 16
|
||||||
|
PLATFORM_WebGLPlayer = 17
|
||||||
|
PLATFORM_WSAPlayerX86 = 18
|
||||||
|
PLATFORM_WSAPlayerX64 = 19
|
||||||
|
PLATFORM_WSAPlayerARM = 20
|
||||||
|
PLATFORM_PS4 = 25
|
||||||
|
PLATFORM_XboxOne = 27
|
||||||
|
PLATFORM_tvOS = 31
|
||||||
|
PLATFORM_Switch = 32
|
||||||
|
PLATFORM_Lumin = 33
|
||||||
|
PLATFORM_Stadia = 34
|
||||||
|
PLATFORM_CloudRendering = 35
|
||||||
|
PLATFORM_PS5 = 36
|
||||||
|
)
|
6
src/enum/playercollision.go
Normal file
6
src/enum/playercollision.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
PLAYER_COLLISION_RADIUS = 0.2234
|
||||||
|
PLAYER_COLLISION_OFFSET_Y = -0.3636
|
||||||
|
)
|
75
src/enum/playercolor.go
Normal file
75
src/enum/playercolor.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
var playerColorNames = []string{
|
||||||
|
"Red",
|
||||||
|
"Blue",
|
||||||
|
"Green",
|
||||||
|
"Pink",
|
||||||
|
"Orange",
|
||||||
|
"Yellow",
|
||||||
|
"Grey",
|
||||||
|
"White",
|
||||||
|
"Purple",
|
||||||
|
"Brown",
|
||||||
|
"Cyan",
|
||||||
|
"Light Green",
|
||||||
|
}
|
||||||
|
|
||||||
|
var playerColors = []int{
|
||||||
|
rgb(198, 17, 17),
|
||||||
|
rgb(19, 46, 210),
|
||||||
|
rgb(17, 128, 45),
|
||||||
|
rgb(238, 84, 187),
|
||||||
|
rgb(240, 125, 13),
|
||||||
|
rgb(246, 246, 87),
|
||||||
|
rgb(63, 71, 78),
|
||||||
|
rgb(215, 225, 241),
|
||||||
|
rgb(107, 47, 188),
|
||||||
|
rgb(113, 73, 30),
|
||||||
|
rgb(56, 255, 221),
|
||||||
|
rgb(80, 240, 57),
|
||||||
|
}
|
||||||
|
|
||||||
|
var playerShadedColors = []int{
|
||||||
|
rgb(122, 8, 56),
|
||||||
|
rgb(9, 21, 142),
|
||||||
|
rgb(10, 77, 46),
|
||||||
|
rgb(172, 43, 174),
|
||||||
|
rgb(180, 62, 21),
|
||||||
|
rgb(195, 136, 34),
|
||||||
|
rgb(30, 31, 38),
|
||||||
|
rgb(132, 149, 192),
|
||||||
|
rgb(59, 23, 124),
|
||||||
|
rgb(94, 38, 21),
|
||||||
|
rgb(36, 169, 191),
|
||||||
|
rgb(21, 168, 66),
|
||||||
|
}
|
||||||
|
|
||||||
|
func rgb(r int, g int, b int) int {
|
||||||
|
return r<<16 + g<<8 + b
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPlayerTotalColors() int {
|
||||||
|
return len(playerColors)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPlayerColorName(a int) string {
|
||||||
|
if a < 0 || a > len(playerColorNames) {
|
||||||
|
return "Invalid Color"
|
||||||
|
}
|
||||||
|
return playerColorNames[a]
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPlayerMainColor(a int) int {
|
||||||
|
if a < 0 || a > len(playerColors) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return playerColors[a]
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPlayerShadedColor(a int) int {
|
||||||
|
if a < 0 || a > len(playerShadedColors) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return playerShadedColors[a]
|
||||||
|
}
|
6
src/enum/playerspeed.go
Normal file
6
src/enum/playerspeed.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
PLAYER_SPEED = 4.5
|
||||||
|
PLAYER_GHOST_SPEED = 3.0
|
||||||
|
)
|
6
src/enum/quickchatmode.go
Normal file
6
src/enum/quickchatmode.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
FREE_CHAT_OR_QUICK_CHAT = 1
|
||||||
|
QUICK_CHAT_ONLY = 2
|
||||||
|
)
|
9
src/enum/reportoutcome.go
Normal file
9
src/enum/reportoutcome.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
REPORTOUTCOME_NOT_REPORTED_UNKNOWN = 0
|
||||||
|
REPORTOUTCOME_NOT_REPORTED_NO_ACCOUNT = 1
|
||||||
|
REPORTOUTCOME_NOT_REPORTED_NOT_FOUND = 2
|
||||||
|
REPORTOUTCOME_NOT_REPORTED_RATE_LIMIT = 3
|
||||||
|
REPORTOUTCOME_REPORTED = 4
|
||||||
|
)
|
8
src/enum/reportreason.go
Normal file
8
src/enum/reportreason.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
REPORTREASON_INAPPROPRIATE_NAME = 0
|
||||||
|
REPORTREASON_INAPPROPRIATE_CHAT = 1
|
||||||
|
REPORTREASON_CHEATING_HACKING = 2
|
||||||
|
REPORTREASON_HARASSMENT_MISCONDUCT = 3
|
||||||
|
)
|
36
src/enum/rpccall.go
Normal file
36
src/enum/rpccall.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
RPC_PLAY_ANIMATION = 0x00
|
||||||
|
RPC_COMPLETE_TASK = 0x01
|
||||||
|
RPC_SYNC_SETTINGS = 0x02
|
||||||
|
RPC_SET_INFECTED = 0x03
|
||||||
|
RPC_EXILED = 0x04
|
||||||
|
RPC_CHECK_NAME = 0x05
|
||||||
|
RPC_SET_NAME = 0x06
|
||||||
|
RPC_CHECK_COLOR = 0x07
|
||||||
|
RPC_SET_COLOR = 0x08
|
||||||
|
RPC_SET_HAT = 0x09
|
||||||
|
RPC_SET_SKIN = 0x0a
|
||||||
|
RPC_REPORT_DEAD_BODY = 0x0b
|
||||||
|
RPC_MURDER_PLAYER = 0x0c
|
||||||
|
RPC_SEND_CHAT = 0x0d
|
||||||
|
RPC_START_MEETING = 0x0e
|
||||||
|
RPC_SET_SCANNER = 0x0f
|
||||||
|
RPC_SEND_CHAT_NOTE = 0x10
|
||||||
|
RPC_SET_PET = 0x11
|
||||||
|
RPC_SET_START_COUNTER = 0x12
|
||||||
|
RPC_ENTER_VENT = 0x13
|
||||||
|
RPC_EXIT_VENT = 0x14
|
||||||
|
RPC_SNAP_TO = 0x15
|
||||||
|
RPC_CLOSE = 0x16
|
||||||
|
RPC_VOTING_COMPLETE = 0x17
|
||||||
|
RPC_CAST_VOTE = 0x18
|
||||||
|
RPC_CLEAR_VOTE = 0x19
|
||||||
|
RPC_ADD_VOTE = 0x1a
|
||||||
|
RPC_CLOSE_DOORS_OF_TYPE = 0x1b
|
||||||
|
RPC_REPAIR_SYSTEM = 0x1c
|
||||||
|
RPC_SET_TASKS = 0x1d
|
||||||
|
RPC_CLIMB_LADDER = 0x1f
|
||||||
|
RPC_USE_PLATFORM = 0x20
|
||||||
|
)
|
9
src/enum/screenstate.go
Normal file
9
src/enum/screenstate.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCREEN_TITLE = 0
|
||||||
|
SCREEN_WAITING = 1
|
||||||
|
SCREEN_LOBBY = 2
|
||||||
|
SCREEN_INGAME = 3
|
||||||
|
SCREEN_ERROR = 4
|
||||||
|
)
|
23
src/enum/skin.go
Normal file
23
src/enum/skin.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
SKIN_NONE = 0
|
||||||
|
SKIN_ASTRONAUT = 1
|
||||||
|
SKIN_CAPTAIN = 2
|
||||||
|
SKIN_MECHANIC = 3
|
||||||
|
SKIN_MILITARY = 4
|
||||||
|
SKIN_POLICE = 5
|
||||||
|
SKIN_SCIENTIST = 6
|
||||||
|
SKIN_SUIT_BLACK = 7
|
||||||
|
SKIN_SUIT_WHITE = 8
|
||||||
|
SKIN_WALL_GUARD = 9
|
||||||
|
SKIN_HAZMAT = 10
|
||||||
|
SKIN_SECURITY_GUARD = 11
|
||||||
|
SKIN_TARMAC = 12
|
||||||
|
SKIN_MINER = 13
|
||||||
|
SKIN_WINTER = 14
|
||||||
|
SKIN_ARCHAEOLOGIST = 15
|
||||||
|
SKIN_PRISONER = 16
|
||||||
|
SKIN_CCC = 17
|
||||||
|
SKIN_RIGHT_HAND_MAN_REBORN = 18
|
||||||
|
)
|
6
src/enum/spawnflag.go
Normal file
6
src/enum/spawnflag.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
SPAWNFLAG_NONE = 0
|
||||||
|
SPAWNFLAG_IS_CLIENT_CHARACTER = 1
|
||||||
|
)
|
13
src/enum/spawntype.go
Normal file
13
src/enum/spawntype.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
SPAWNTYPE_SKELD_SHIP_STATUS = 0
|
||||||
|
SPAWNTYPE_MEETING_HUD = 1
|
||||||
|
SPAWNTYPE_LOBBY_BEHAVIOUR = 2
|
||||||
|
SPAWNTYPE_GAME_DATA = 3
|
||||||
|
SPAWNTYPE_PLAYER_CONTROL = 4
|
||||||
|
SPAWNTYPE_MIRA_SHIP_STATUS = 5
|
||||||
|
SPAWNTYPE_POLUS_SHIP_STATUS = 6
|
||||||
|
SPAWNTYPE_DLEKS_SHIP_STATUS = 7
|
||||||
|
SPAWNTYPE_AIRSHIP_STATUS = 8
|
||||||
|
)
|
53
src/enum/systemtype.go
Normal file
53
src/enum/systemtype.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
SYSTEMTYPE_HALLWAY = 0
|
||||||
|
SYSTEMTYPE_STORAGE = 1
|
||||||
|
SYSTEMTYPE_CAFETERIA = 2
|
||||||
|
SYSTEMTYPE_REACTOR = 3
|
||||||
|
SYSTEMTYPE_UPPER_ENGINE = 4
|
||||||
|
SYSTEMTYPE_NAVIGATION = 5
|
||||||
|
SYSTEMTYPE_ADMIN = 6
|
||||||
|
SYSTEMTYPE_ELECTRICAL = 7
|
||||||
|
SYSTEMTYPE_O2 = 8
|
||||||
|
SYSTEMTYPE_SHIELDS = 9
|
||||||
|
SYSTEMTYPE_MEDBAY = 10
|
||||||
|
SYSTEMTYPE_SECURITY = 11
|
||||||
|
SYSTEMTYPE_WEAPONS = 12
|
||||||
|
SYSTEMTYPE_LOWER_ENGINE = 13
|
||||||
|
SYSTEMTYPE_COMMUNICATIONS = 14
|
||||||
|
SYSTEMTYPE_SHIP_TASKS = 15
|
||||||
|
SYSTEMTYPE_DOORS = 16
|
||||||
|
SYSTEMTYPE_SABOTAGE = 17
|
||||||
|
SYSTEMTYPE_DECONTAMINATION = 18
|
||||||
|
SYSTEMTYPE_LAUNCHPAD = 19
|
||||||
|
SYSTEMTYPE_LOCKER_ROOM = 20
|
||||||
|
SYSTEMTYPE_LABORATORY = 21
|
||||||
|
SYSTEMTYPE_BALCONY = 22
|
||||||
|
SYSTEMTYPE_OFFICE = 23
|
||||||
|
SYSTEMTYPE_GREENHOUSE = 24
|
||||||
|
SYSTEMTYPE_DROPSHIP = 25
|
||||||
|
SYSTEMTYPE_DECONTAMINATION_2 = 26
|
||||||
|
SYSTEMTYPE_OUTSIDE = 27
|
||||||
|
SYSTEMTYPE_SPECIMENS = 28
|
||||||
|
SYSTEMTYPE_BOILER_ROOM = 29
|
||||||
|
SYSTEMTYPE_VAULT_ROOM = 30
|
||||||
|
SYSTEMTYPE_COCKPIT = 31
|
||||||
|
SYSTEMTYPE_ARMORY = 32
|
||||||
|
SYSTEMTYPE_KITCHEN = 33
|
||||||
|
SYSTEMTYPE_VIEWING_DECK = 34
|
||||||
|
SYSTEMTYPE_HALL_OF_PORTRAITS = 35
|
||||||
|
SYSTEMTYPE_CARGO_BAY = 36
|
||||||
|
SYSTEMTYPE_VENTILATION = 37
|
||||||
|
SYSTEMTYPE_SHOWERS = 38
|
||||||
|
SYSTEMTYPE_ENGINE = 39
|
||||||
|
SYSTEMTYPE_BRIG = 40
|
||||||
|
SYSTEMTYPE_MEETING_ROOM = 41
|
||||||
|
SYSTEMTYPE_RECORDS = 42
|
||||||
|
SYSTEMTYPE_LOUNGE = 43
|
||||||
|
SYSTEMTYPE_GAP_ROOM = 44
|
||||||
|
SYSTEMTYPE_MAIN_HALL = 45
|
||||||
|
SYSTEMTYPE_MEDICAL = 46
|
||||||
|
|
||||||
|
TOTAL_SYSTEMTYPE = 47
|
||||||
|
)
|
7
src/enum/taskbarmode.go
Normal file
7
src/enum/taskbarmode.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
TASKBARMODE_ALWAYS = 0
|
||||||
|
TASKBARMODE_MEETINGS = 1
|
||||||
|
TASKBARMODE_NEVER = 2
|
||||||
|
)
|
64
src/enum/tasktypes.go
Normal file
64
src/enum/tasktypes.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
const (
|
||||||
|
TASKTYPES_SUBMIT_SCAN = 0
|
||||||
|
TASKTYPES_PRIME_SHIELDS = 1
|
||||||
|
TASKTYPES_FUEL_ENGINES = 2
|
||||||
|
TASKTYPES_CHART_COURSE = 3
|
||||||
|
TASKTYPES_START_REACTOR = 4
|
||||||
|
TASKTYPES_SWIPE_CARD = 5
|
||||||
|
TASKTYPES_CLEAR_ASTEROIDS = 6
|
||||||
|
TASKTYPES_UPLOAD_DATA = 7
|
||||||
|
TASKTYPES_INSPECT_SAMPLE = 8
|
||||||
|
TASKTYPES_EMPTY_CHUTE = 9
|
||||||
|
TASKTYPES_EMPTY_GARBAGE = 10
|
||||||
|
TASKTYPES_ALIGN_ENGINE_OUTPUT = 11
|
||||||
|
TASKTYPES_FIX_WIRING = 12
|
||||||
|
TASKTYPES_CALIBRATE_DISTRIBUTOR = 13
|
||||||
|
TASKTYPES_DIVERT_POWER = 14
|
||||||
|
TASKTYPES_UNLOCK_MANIFOLDS = 15
|
||||||
|
TASKTYPES_RESET_REACTOR = 16
|
||||||
|
TASKTYPES_FIX_LIGHTS = 17
|
||||||
|
TASKTYPES_CLEAN_O2_FILTER = 18
|
||||||
|
TASKTYPES_FIX_COMMS = 19
|
||||||
|
TASKTYPES_RESTORE_O2 = 20
|
||||||
|
TASKTYPES_STABILIZE_STEERING = 21
|
||||||
|
TASKTYPES_ASSEMBLE_ARTIFACT = 22
|
||||||
|
TASKTYPES_SORT_SAMPLES = 23
|
||||||
|
TASKTYPES_MEASURE_WEATHER = 24
|
||||||
|
TASKTYPES_ENTER_ID_CODE = 25
|
||||||
|
TASKTYPES_BUY_BEVERAGE = 26
|
||||||
|
TASKTYPES_PROCESS_DATA = 27
|
||||||
|
TASKTYPES_RUN_DIAGNOSTICS = 28
|
||||||
|
TASKTYPES_WATER_PLANTS = 29
|
||||||
|
TASKTYPES_MONITOR_O2 = 30
|
||||||
|
TASKTYPES_STORE_ARTIFACTS = 31
|
||||||
|
TASKTYPES_FILL_CANISTERS = 32
|
||||||
|
TASKTYPES_ACTIVATE_WEATHER_NODES = 33
|
||||||
|
TASKTYPES_INSERT_KEYS = 34
|
||||||
|
TASKTYPES_RESET_SEISMIC = 35
|
||||||
|
TASKTYPES_SCAN_BOARDING_PASS = 36
|
||||||
|
TASKTYPES_OPEN_WATERWAYS = 37
|
||||||
|
TASKTYPES_REPLACE_WATER_JUG = 38
|
||||||
|
TASKTYPES_REPAIR_DRILL = 39
|
||||||
|
TASKTYPES_ALIGN_TELESCOPE = 40
|
||||||
|
TASKTYPES_RECORD_TEMPERATURE = 41
|
||||||
|
TASKTYPES_REBOOT_WIFI = 42
|
||||||
|
TASKTYPES_POLISH_RUBY = 43
|
||||||
|
TASKTYPES_RESET_BREAKERS = 44
|
||||||
|
TASKTYPES_DECONTAMINATE = 45
|
||||||
|
TASKTYPES_MAKE_BURGER = 46
|
||||||
|
TASKTYPES_UNLOCK_SAFE = 47
|
||||||
|
TASKTYPES_SORT_RECORDS = 48
|
||||||
|
TASKTYPES_PUT_AWAY_PISTOLS = 49
|
||||||
|
TASKTYPES_FIX_SHOWER = 50
|
||||||
|
TASKTYPES_CLEAN_TOILET = 51
|
||||||
|
TASKTYPES_DRESS_MANNEQUIN = 52
|
||||||
|
TASKTYPES_PICK_UP_TOWELS = 53
|
||||||
|
TASKTYPES_REWIND_TAPES = 54
|
||||||
|
TASKTYPES_START_FANS = 55
|
||||||
|
TASKTYPES_DEVELOP_PHOTOS = 56
|
||||||
|
TASKTYPES_GET_BIGGOL_SWORD = 57
|
||||||
|
TASKTYPES_PUT_AWAY_RIFLES = 58
|
||||||
|
TASKTYPES_STOP_CHARLES = 59
|
||||||
|
)
|
23
src/gamedata/01_data.go
Normal file
23
src/gamedata/01_data.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DataH2G struct {
|
||||||
|
Component *protocol.UpdateComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DataH2G) AsHazel() *protocol.Hazel {
|
||||||
|
var a protocol.HazelPayload = d
|
||||||
|
return protocol.NewHazelFromPayload(&a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DataH2G) TypeCode() byte { return 0x01 }
|
||||||
|
func (d *DataH2G) Write(packet *protocol.Packet) {
|
||||||
|
d.Component.Write(packet)
|
||||||
|
}
|
||||||
|
func (d *DataH2G) Read(packet *protocol.Packet) {
|
||||||
|
d.Component = &protocol.UpdateComponent{}
|
||||||
|
d.Component.Read(packet)
|
||||||
|
}
|
501
src/gamedata/02_rpc.go
Normal file
501
src/gamedata/02_rpc.go
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// RPC base
|
||||||
|
//
|
||||||
|
|
||||||
|
type Rpc struct {
|
||||||
|
SenderNetID uint32
|
||||||
|
RPCCallID byte
|
||||||
|
Sub *RpcSub
|
||||||
|
UnderlyingHazel *protocol.Hazel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRpcFromHazel(h *protocol.Hazel) *Rpc {
|
||||||
|
a := &Rpc{}
|
||||||
|
a.SenderNetID = h.GetUnderlyingPacket().ReadPackedUInt32()
|
||||||
|
a.RPCCallID = h.GetUnderlyingPacket().Read()
|
||||||
|
a.UnderlyingHazel = h
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRpcFromRpcSub(senderNetID uint32, sub *RpcSub) *Rpc {
|
||||||
|
return &Rpc{
|
||||||
|
SenderNetID: senderNetID,
|
||||||
|
RPCCallID: (*sub).CallCode(),
|
||||||
|
Sub: sub,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Rpc) GetUnderlyingHazel() *protocol.Hazel {
|
||||||
|
return d.UnderlyingHazel
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Rpc) AsHazel() *protocol.Hazel {
|
||||||
|
var a protocol.HazelPayload = d
|
||||||
|
return protocol.NewHazelFromPayload(&a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Rpc) TypeCode() byte { return 0x02 }
|
||||||
|
func (d *Rpc) Write(packet *protocol.Packet) {
|
||||||
|
packet.WritePackedUInt32(d.SenderNetID)
|
||||||
|
packet.Write(d.RPCCallID)
|
||||||
|
(*d.Sub).WriteToPacket(packet)
|
||||||
|
}
|
||||||
|
func (d *Rpc) Read(packet *protocol.Packet) {
|
||||||
|
d.SenderNetID = packet.ReadPackedUInt32()
|
||||||
|
d.RPCCallID = packet.Read()
|
||||||
|
// TODO: finish this
|
||||||
|
}
|
||||||
|
|
||||||
|
type RpcSub interface {
|
||||||
|
CallCode() byte
|
||||||
|
WriteToPacket(packet *protocol.Packet)
|
||||||
|
ReadFromPacket(packet *protocol.Packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x00 RpcPlayAnimation
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcPlayAnimation struct{ TaskID byte }
|
||||||
|
|
||||||
|
func (d *RpcPlayAnimation) CallCode() byte { return enum.RPC_PLAY_ANIMATION }
|
||||||
|
func (d *RpcPlayAnimation) WriteToPacket(packet *protocol.Packet) { packet.Write(d.TaskID) }
|
||||||
|
func (d *RpcPlayAnimation) ReadFromPacket(packet *protocol.Packet) { d.TaskID = packet.Read() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x01 RpcCompleteTask
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcCompleteTask struct{ TaskIndex uint32 }
|
||||||
|
|
||||||
|
func (d *RpcCompleteTask) CallCode() byte { return enum.RPC_COMPLETE_TASK }
|
||||||
|
func (d *RpcCompleteTask) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.WritePackedUInt32(d.TaskIndex)
|
||||||
|
}
|
||||||
|
func (d *RpcCompleteTask) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.TaskIndex = packet.ReadPackedUInt32()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x02 RpcSyncSettings
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSyncSettings struct{ Options *protocol.GameOptionsData }
|
||||||
|
|
||||||
|
func (d *RpcSyncSettings) CallCode() byte { return enum.RPC_SYNC_SETTINGS }
|
||||||
|
func (d *RpcSyncSettings) WriteToPacket(packet *protocol.Packet) { d.Options.Write(packet) }
|
||||||
|
func (d *RpcSyncSettings) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.Options = protocol.NewGameOptionsDataFromPacket(packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x03 RpcSetInfected
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSetInfected struct{ Impostors []byte }
|
||||||
|
|
||||||
|
func (d *RpcSetInfected) CallCode() byte { return enum.RPC_SET_INFECTED }
|
||||||
|
func (d *RpcSetInfected) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.Write(byte(len(d.Impostors)))
|
||||||
|
for i := 0; i < len(d.Impostors); i++ {
|
||||||
|
packet.Write(d.Impostors[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (d *RpcSetInfected) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.Impostors = make([]byte, packet.Read())
|
||||||
|
for i := 0; i < len(d.Impostors); i++ {
|
||||||
|
d.Impostors[i] = packet.Read()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x04 RpcExiled
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcExiled struct{}
|
||||||
|
|
||||||
|
func (d *RpcExiled) CallCode() byte { return enum.RPC_EXILED }
|
||||||
|
func (d *RpcExiled) WriteToPacket(packet *protocol.Packet) {}
|
||||||
|
func (d *RpcExiled) ReadFromPacket(packet *protocol.Packet) {}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x05 RpcCheckName
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcCheckName struct{ Name string }
|
||||||
|
|
||||||
|
func (d *RpcCheckName) CallCode() byte { return enum.RPC_CHECK_NAME }
|
||||||
|
func (d *RpcCheckName) WriteToPacket(packet *protocol.Packet) { packet.WriteString(d.Name) }
|
||||||
|
func (d *RpcCheckName) ReadFromPacket(packet *protocol.Packet) { d.Name = packet.ReadString() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x06 RpcSetName
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSetName struct{ Name string }
|
||||||
|
|
||||||
|
func (d *RpcSetName) CallCode() byte { return enum.RPC_SET_NAME }
|
||||||
|
func (d *RpcSetName) WriteToPacket(packet *protocol.Packet) { packet.WriteString(d.Name) }
|
||||||
|
func (d *RpcSetName) ReadFromPacket(packet *protocol.Packet) { d.Name = packet.ReadString() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x07 RpcCheckColor
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcCheckColor struct{ Color byte }
|
||||||
|
|
||||||
|
func (d *RpcCheckColor) CallCode() byte { return enum.RPC_CHECK_COLOR }
|
||||||
|
func (d *RpcCheckColor) WriteToPacket(packet *protocol.Packet) { packet.Write(d.Color) }
|
||||||
|
func (d *RpcCheckColor) ReadFromPacket(packet *protocol.Packet) { d.Color = packet.Read() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x08 RpcSetColor
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSetColor struct{ Color byte }
|
||||||
|
|
||||||
|
func (d *RpcSetColor) CallCode() byte { return enum.RPC_SET_COLOR }
|
||||||
|
func (d *RpcSetColor) WriteToPacket(packet *protocol.Packet) { packet.Write(d.Color) }
|
||||||
|
func (d *RpcSetColor) ReadFromPacket(packet *protocol.Packet) { d.Color = packet.Read() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x09 RpcSetHat
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSetHat struct{ HatID uint32 }
|
||||||
|
|
||||||
|
func (d *RpcSetHat) CallCode() byte { return enum.RPC_SET_HAT }
|
||||||
|
func (d *RpcSetHat) WriteToPacket(packet *protocol.Packet) { packet.WritePackedUInt32(d.HatID) }
|
||||||
|
func (d *RpcSetHat) ReadFromPacket(packet *protocol.Packet) { d.HatID = packet.ReadPackedUInt32() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x0a RpcSetSkin
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSetSkin struct{ SkinID uint32 }
|
||||||
|
|
||||||
|
func (d *RpcSetSkin) CallCode() byte { return enum.RPC_SET_SKIN }
|
||||||
|
func (d *RpcSetSkin) WriteToPacket(packet *protocol.Packet) { packet.WritePackedUInt32(d.SkinID) }
|
||||||
|
func (d *RpcSetSkin) ReadFromPacket(packet *protocol.Packet) { d.SkinID = packet.ReadPackedUInt32() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x0b RpcReportDeadBody
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcReportDeadBody struct{ VictimPlayerID byte }
|
||||||
|
|
||||||
|
func (d *RpcReportDeadBody) CallCode() byte { return enum.RPC_REPORT_DEAD_BODY }
|
||||||
|
func (d *RpcReportDeadBody) WriteToPacket(packet *protocol.Packet) { packet.Write(d.VictimPlayerID) }
|
||||||
|
func (d *RpcReportDeadBody) ReadFromPacket(packet *protocol.Packet) { d.VictimPlayerID = packet.Read() }
|
||||||
|
func (d *RpcReportDeadBody) IsEmergencyMeetingButton() bool { return d.VictimPlayerID == 255 }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x0c RpcMurderPlayer
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcMurderPlayer struct{ VictimNetID uint32 }
|
||||||
|
|
||||||
|
func (d *RpcMurderPlayer) CallCode() byte { return enum.RPC_MURDER_PLAYER }
|
||||||
|
func (d *RpcMurderPlayer) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.WritePackedUInt32(d.VictimNetID)
|
||||||
|
}
|
||||||
|
func (d *RpcMurderPlayer) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.VictimNetID = packet.ReadPackedUInt32()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x0d RpcSendChat
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSendChat struct{ Message string }
|
||||||
|
|
||||||
|
func (d *RpcSendChat) CallCode() byte { return enum.RPC_SEND_CHAT }
|
||||||
|
func (d *RpcSendChat) WriteToPacket(packet *protocol.Packet) { packet.WriteString(d.Message) }
|
||||||
|
func (d *RpcSendChat) ReadFromPacket(packet *protocol.Packet) { d.Message = packet.ReadString() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x0e RpcStartMeeting
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcStartMeeting struct{ VictimPlayerID byte }
|
||||||
|
|
||||||
|
func (d *RpcStartMeeting) CallCode() byte { return enum.RPC_START_MEETING }
|
||||||
|
func (d *RpcStartMeeting) WriteToPacket(packet *protocol.Packet) { packet.Write(d.VictimPlayerID) }
|
||||||
|
func (d *RpcStartMeeting) ReadFromPacket(packet *protocol.Packet) { d.VictimPlayerID = packet.Read() }
|
||||||
|
func (d *RpcStartMeeting) IsEmergencyMeetingButton() bool { return d.VictimPlayerID == 255 }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x0f RpcSetScanner
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSetScanner struct {
|
||||||
|
IsScanning bool
|
||||||
|
SequenceID byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcSetScanner) CallCode() byte { return enum.RPC_SET_SCANNER }
|
||||||
|
func (d *RpcSetScanner) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.WriteBool(d.IsScanning)
|
||||||
|
packet.Write(d.SequenceID)
|
||||||
|
}
|
||||||
|
func (d *RpcSetScanner) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.IsScanning = packet.ReadBool()
|
||||||
|
d.SequenceID = packet.Read()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x10 RpcSendChatNote
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSendChatNote struct {
|
||||||
|
PlayerID byte
|
||||||
|
ChatNoteType byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcSendChatNote) CallCode() byte { return enum.RPC_SEND_CHAT_NOTE }
|
||||||
|
func (d *RpcSendChatNote) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.Write(d.PlayerID)
|
||||||
|
packet.Write(d.ChatNoteType)
|
||||||
|
}
|
||||||
|
func (d *RpcSendChatNote) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.PlayerID = packet.Read()
|
||||||
|
d.ChatNoteType = packet.Read()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x11 RpcSetPet
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSetPet struct{ PetID uint32 }
|
||||||
|
|
||||||
|
func (d *RpcSetPet) CallCode() byte { return enum.RPC_SET_PET }
|
||||||
|
func (d *RpcSetPet) WriteToPacket(packet *protocol.Packet) { packet.WritePackedUInt32(d.PetID) }
|
||||||
|
func (d *RpcSetPet) ReadFromPacket(packet *protocol.Packet) { d.PetID = packet.ReadPackedUInt32() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x12 RpcSetStartCounter
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSetStartCounter struct {
|
||||||
|
SequenceID uint32
|
||||||
|
TimeRemaining byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcSetStartCounter) CallCode() byte { return enum.RPC_SET_START_COUNTER }
|
||||||
|
func (d *RpcSetStartCounter) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.WritePackedUInt32(d.SequenceID)
|
||||||
|
packet.Write(d.TimeRemaining)
|
||||||
|
}
|
||||||
|
func (d *RpcSetStartCounter) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.SequenceID = packet.ReadPackedUInt32()
|
||||||
|
d.TimeRemaining = packet.Read()
|
||||||
|
}
|
||||||
|
func (d *RpcSetStartCounter) ShouldResetTimer() bool { return d.TimeRemaining == 0xff }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x13 RpcEnterVent
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcEnterVent struct{ VentID uint32 }
|
||||||
|
|
||||||
|
func (d *RpcEnterVent) CallCode() byte { return enum.RPC_ENTER_VENT }
|
||||||
|
func (d *RpcEnterVent) WriteToPacket(packet *protocol.Packet) { packet.WritePackedUInt32(d.VentID) }
|
||||||
|
func (d *RpcEnterVent) ReadFromPacket(packet *protocol.Packet) { d.VentID = packet.ReadPackedUInt32() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x14 RpcExitVent
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcExitVent struct{ VentID uint32 }
|
||||||
|
|
||||||
|
func (d *RpcExitVent) CallCode() byte { return enum.RPC_EXIT_VENT }
|
||||||
|
func (d *RpcExitVent) WriteToPacket(packet *protocol.Packet) { packet.WritePackedUInt32(d.VentID) }
|
||||||
|
func (d *RpcExitVent) ReadFromPacket(packet *protocol.Packet) { d.VentID = packet.ReadPackedUInt32() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x15 RpcSnapTo
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSnapTo struct {
|
||||||
|
Position util.Vec2
|
||||||
|
LastSequenceID uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcSnapTo) CallCode() byte { return enum.RPC_SNAP_TO }
|
||||||
|
func (d *RpcSnapTo) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.WriteVector2(d.Position)
|
||||||
|
packet.WriteUInt16(d.LastSequenceID)
|
||||||
|
}
|
||||||
|
func (d *RpcSnapTo) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.Position = packet.ReadVector2()
|
||||||
|
d.LastSequenceID = packet.ReadUInt16()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x16 RpcClose
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcClose struct{}
|
||||||
|
|
||||||
|
func (d *RpcClose) CallCode() byte { return enum.RPC_CLOSE }
|
||||||
|
func (d *RpcClose) WriteToPacket(packet *protocol.Packet) {}
|
||||||
|
func (d *RpcClose) ReadFromPacket(packet *protocol.Packet) {}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x17 RpcVotingComplete
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcVotingComplete struct {
|
||||||
|
VoteStates []byte
|
||||||
|
ExiledPlayerID byte
|
||||||
|
IsTie bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: write serializer for voting complete
|
||||||
|
func (d *RpcVotingComplete) CallCode() byte { return enum.RPC_VOTING_COMPLETE }
|
||||||
|
func (d *RpcVotingComplete) WriteToPacket(packet *protocol.Packet) {}
|
||||||
|
func (d *RpcVotingComplete) ReadFromPacket(packet *protocol.Packet) {}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x18 RpcCastVote
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcCastVote struct {
|
||||||
|
VotingPlayerID byte
|
||||||
|
SuspectPlayerID byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcCastVote) CallCode() byte { return enum.RPC_CAST_VOTE }
|
||||||
|
func (d *RpcCastVote) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.Write(d.VotingPlayerID)
|
||||||
|
packet.Write(d.SuspectPlayerID)
|
||||||
|
}
|
||||||
|
func (d *RpcCastVote) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.VotingPlayerID = packet.Read()
|
||||||
|
d.SuspectPlayerID = packet.Read()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x19 RpcClearVote
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcClearVote struct{}
|
||||||
|
|
||||||
|
func (d *RpcClearVote) CallCode() byte { return enum.RPC_CLEAR_VOTE }
|
||||||
|
func (d *RpcClearVote) WriteToPacket(packet *protocol.Packet) {}
|
||||||
|
func (d *RpcClearVote) ReadFromPacket(packet *protocol.Packet) {}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x1a RpcAddVote
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcAddVote struct {
|
||||||
|
VotingClientID uint32
|
||||||
|
TargetClientID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcAddVote) CallCode() byte { return enum.RPC_ADD_VOTE }
|
||||||
|
func (d *RpcAddVote) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.WriteUInt32(d.VotingClientID)
|
||||||
|
packet.WriteUInt32(d.TargetClientID)
|
||||||
|
}
|
||||||
|
func (d *RpcAddVote) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.VotingClientID = packet.ReadUInt32()
|
||||||
|
d.TargetClientID = packet.ReadUInt32()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x1b RpcCloseDoorsOfType
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcCloseDoorsOfType struct {
|
||||||
|
SystemID byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcCloseDoorsOfType) CallCode() byte { return enum.RPC_CLOSE_DOORS_OF_TYPE }
|
||||||
|
func (d *RpcCloseDoorsOfType) WriteToPacket(packet *protocol.Packet) { packet.Write(d.SystemID) }
|
||||||
|
func (d *RpcCloseDoorsOfType) ReadFromPacket(packet *protocol.Packet) { d.SystemID = packet.Read() }
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x1c RpcRepairSystem
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcRepairSystem struct {
|
||||||
|
SystemID byte
|
||||||
|
PlayerControlNetID uint32
|
||||||
|
Amount byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcRepairSystem) CallCode() byte { return enum.RPC_REPAIR_SYSTEM }
|
||||||
|
func (d *RpcRepairSystem) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.Write(d.SystemID)
|
||||||
|
packet.WritePackedUInt32(d.PlayerControlNetID)
|
||||||
|
packet.Write(d.Amount)
|
||||||
|
}
|
||||||
|
func (d *RpcRepairSystem) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.SystemID = packet.Read()
|
||||||
|
d.PlayerControlNetID = packet.ReadPackedUInt32()
|
||||||
|
d.Amount = packet.Read()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x1d RpcSetTasks
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcSetTasks struct {
|
||||||
|
PlayerID byte
|
||||||
|
Tasks []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcSetTasks) CallCode() byte { return enum.RPC_SET_TASKS }
|
||||||
|
func (d *RpcSetTasks) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.Write(d.PlayerID)
|
||||||
|
packet.WritePackedUInt32(uint32(len(d.Tasks)))
|
||||||
|
for i := 0; i < len(d.Tasks); i++ {
|
||||||
|
packet.Write(d.Tasks[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (d *RpcSetTasks) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.PlayerID = packet.Read()
|
||||||
|
d.Tasks = make([]byte, packet.ReadPackedUInt32())
|
||||||
|
for i := 0; i < len(d.Tasks); i++ {
|
||||||
|
d.Tasks[i] = packet.Read()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x1f RpcClimbLadder
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcClimbLadder struct {
|
||||||
|
LadderID byte
|
||||||
|
SequenceID byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RpcClimbLadder) CallCode() byte { return enum.RPC_CLIMB_LADDER }
|
||||||
|
func (d *RpcClimbLadder) WriteToPacket(packet *protocol.Packet) {
|
||||||
|
packet.Write(d.LadderID)
|
||||||
|
packet.Write(d.SequenceID)
|
||||||
|
}
|
||||||
|
func (d *RpcClimbLadder) ReadFromPacket(packet *protocol.Packet) {
|
||||||
|
d.LadderID = packet.Read()
|
||||||
|
d.SequenceID = packet.Read()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 0x1f RpcUsePlatform
|
||||||
|
//
|
||||||
|
|
||||||
|
type RpcUsePlatform struct{}
|
||||||
|
|
||||||
|
func (d *RpcUsePlatform) CallCode() byte { return enum.RPC_CLIMB_LADDER }
|
||||||
|
func (d *RpcUsePlatform) WriteToPacket(packet *protocol.Packet) {}
|
||||||
|
func (d *RpcUsePlatform) ReadFromPacket(packet *protocol.Packet) {}
|
36
src/gamedata/04_spawn.go
Normal file
36
src/gamedata/04_spawn.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type SpawnH2G struct {
|
||||||
|
SpawnType uint32
|
||||||
|
OwnerID uint32
|
||||||
|
SpawnFlags byte
|
||||||
|
Components []*protocol.SpawnComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *SpawnH2G) AsHazel() *protocol.Hazel {
|
||||||
|
var a protocol.HazelPayload = d
|
||||||
|
return protocol.NewHazelFromPayload(&a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *SpawnH2G) TypeCode() byte { return 0x04 }
|
||||||
|
|
||||||
|
func (d *SpawnH2G) Write(packet *protocol.Packet) {
|
||||||
|
packet.WritePackedUInt32(d.SpawnType)
|
||||||
|
packet.WritePackedUInt32(d.OwnerID)
|
||||||
|
packet.Write(d.SpawnFlags)
|
||||||
|
for i := 0; i < len(d.Components); i++ {
|
||||||
|
d.Components[i].Write(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (d *SpawnH2G) Read(packet *protocol.Packet) {
|
||||||
|
d.SpawnType = packet.ReadPackedUInt32()
|
||||||
|
d.OwnerID = packet.ReadPackedUInt32()
|
||||||
|
d.SpawnFlags = packet.Read()
|
||||||
|
d.Components = make([]*protocol.SpawnComponent, packet.Read())
|
||||||
|
for i := 0; i < len(d.Components); i++ {
|
||||||
|
d.Components[i] = &protocol.SpawnComponent{}
|
||||||
|
d.Components[i].Read(packet)
|
||||||
|
}
|
||||||
|
}
|
16
src/gamedata/05_despawn.go
Normal file
16
src/gamedata/05_despawn.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type DespawnH2G struct {
|
||||||
|
NetID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DespawnH2G) AsHazel() *protocol.Hazel {
|
||||||
|
var a protocol.HazelPayload = d
|
||||||
|
return protocol.NewHazelFromPayload(&a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DespawnH2G) TypeCode() byte { return 0x05 }
|
||||||
|
func (d *DespawnH2G) Write(packet *protocol.Packet) { packet.WritePackedUInt32(d.NetID) }
|
||||||
|
func (d *DespawnH2G) Read(packet *protocol.Packet) { d.NetID = packet.ReadPackedUInt32() }
|
23
src/gamedata/06_scenechange.go
Normal file
23
src/gamedata/06_scenechange.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type SceneChangeC2H struct {
|
||||||
|
ClientID uint32
|
||||||
|
SceneName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *SceneChangeC2H) AsHazel() *protocol.Hazel {
|
||||||
|
var a protocol.HazelPayload = d
|
||||||
|
return protocol.NewHazelFromPayload(&a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *SceneChangeC2H) TypeCode() byte { return 0x06 }
|
||||||
|
func (d *SceneChangeC2H) Write(packet *protocol.Packet) {
|
||||||
|
packet.WritePackedUInt32(d.ClientID)
|
||||||
|
packet.WriteString(d.SceneName)
|
||||||
|
}
|
||||||
|
func (d *SceneChangeC2H) Read(packet *protocol.Packet) {
|
||||||
|
d.ClientID = packet.ReadPackedUInt32()
|
||||||
|
d.SceneName = packet.ReadString()
|
||||||
|
}
|
16
src/gamedata/07_ready.go
Normal file
16
src/gamedata/07_ready.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type ReadyC2H struct {
|
||||||
|
ReadyClientID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReadyC2H) AsHazel() *protocol.Hazel {
|
||||||
|
var a protocol.HazelPayload = d
|
||||||
|
return protocol.NewHazelFromPayload(&a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReadyC2H) TypeCode() byte { return 0x07 }
|
||||||
|
func (d *ReadyC2H) Write(packet *protocol.Packet) { packet.WritePackedUInt32(d.ReadyClientID) }
|
||||||
|
func (d *ReadyC2H) Read(packet *protocol.Packet) { d.ReadyClientID = packet.ReadPackedUInt32() }
|
5
src/gamedata/08_changesettings.go
Normal file
5
src/gamedata/08_changesettings.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
// ChangeSettingsAll is never used
|
||||||
|
type ChangeSettingsAll struct {
|
||||||
|
}
|
23
src/gamedata/205_clientinfo.go
Normal file
23
src/gamedata/205_clientinfo.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type ClientInfoC2S struct {
|
||||||
|
ClientID uint32
|
||||||
|
PlatformID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ClientInfoC2S) AsHazel() *protocol.Hazel {
|
||||||
|
var a protocol.HazelPayload = d
|
||||||
|
return protocol.NewHazelFromPayload(&a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ClientInfoC2S) TypeCode() byte { return 0xcd }
|
||||||
|
func (d *ClientInfoC2S) Write(packet *protocol.Packet) {
|
||||||
|
packet.WritePackedUInt32(d.ClientID)
|
||||||
|
packet.WritePackedUInt32(d.PlatformID)
|
||||||
|
}
|
||||||
|
func (d *ClientInfoC2S) Read(packet *protocol.Packet) {
|
||||||
|
d.ClientID = packet.ReadPackedUInt32()
|
||||||
|
d.PlatformID = packet.ReadPackedUInt32()
|
||||||
|
}
|
13
src/gamedata/go.mod
Normal file
13
src/gamedata/go.mod
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module codehub.onpointcoding.net/sean/go-susapp/gamedata
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
replace (
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/protocol => ../protocol
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/util => ../util
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/protocol v1.0.0
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/util v1.0.0
|
||||||
|
)
|
35
src/innernetobjects/gamedata.go
Normal file
35
src/innernetobjects/gamedata.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GameData struct {
|
||||||
|
Players []*protocol.PlayerData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *GameData) Write(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
if isSpawn {
|
||||||
|
packet.WriteUInt32(uint32(len(data.Players)))
|
||||||
|
} else {
|
||||||
|
packet.Write(byte(len(data.Players)))
|
||||||
|
}
|
||||||
|
for i := 0; i < len(data.Players); i++ {
|
||||||
|
data.Players[i].Write(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (data *GameData) Read(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
packet.ReadBytes(4)
|
||||||
|
if packet.Dump()[0] == 0x0c {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if isSpawn {
|
||||||
|
data.Players = make([]*protocol.PlayerData, packet.ReadPackedUInt32())
|
||||||
|
} else {
|
||||||
|
data.Players = make([]*protocol.PlayerData, packet.Read())
|
||||||
|
}
|
||||||
|
for i := 0; i < len(data.Players); i++ {
|
||||||
|
data.Players[i] = &protocol.PlayerData{}
|
||||||
|
data.Players[i].Read(packet)
|
||||||
|
}
|
||||||
|
}
|
17
src/innernetobjects/go.mod
Normal file
17
src/innernetobjects/go.mod
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
module codehub.onpointcoding.net/sean/go-susapp/innernetobjects
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
replace (
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/enum => ../enum
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/protocol => ../protocol
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/systemtypes => ../systemtypes
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/util => ../util
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/enum v1.0.0
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/protocol v1.0.0
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/systemtypes v1.0.0
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/util v1.0.0 // indirect
|
||||||
|
)
|
8
src/innernetobjects/innernetobject.go
Normal file
8
src/innernetobjects/innernetobject.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type InnerNetObject interface {
|
||||||
|
Write(packet *protocol.Packet, isSpawn bool)
|
||||||
|
Read(packet *protocol.Packet, isSpawn bool)
|
||||||
|
}
|
33
src/innernetobjects/mirashipstatus.go
Normal file
33
src/innernetobjects/mirashipstatus.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/systemtypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MiraShipStatus struct {
|
||||||
|
Systems map[int]*systemtypes.SystemType
|
||||||
|
SystemsMask uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMiraShipStatus() *MiraShipStatus {
|
||||||
|
a := &MiraShipStatus{}
|
||||||
|
a.Systems = make(map[int]*systemtypes.SystemType)
|
||||||
|
a.Systems[enum.SYSTEMTYPE_REACTOR] = systemtypes.SystemTypeCast(&systemtypes.ReactorSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_ELECTRICAL] = systemtypes.SystemTypeCast(&systemtypes.SwitchSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_O2] = systemtypes.SystemTypeCast(&systemtypes.LifeSuppSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_MEDBAY] = systemtypes.SystemTypeCast(&systemtypes.MedScanSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_COMMUNICATIONS] = systemtypes.SystemTypeCast(&systemtypes.HqHudSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_SABOTAGE] = systemtypes.SystemTypeCast(&systemtypes.SabotageSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_DECONTAMINATION] = systemtypes.SystemTypeCast(&systemtypes.DeconSystem{})
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mira *MiraShipStatus) Write(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
WriteShipStatus(mira.Systems, &mira.SystemsMask, packet, isSpawn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mira *MiraShipStatus) Read(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
ReadShipStatus(mira.Systems, &mira.SystemsMask, packet, isSpawn)
|
||||||
|
}
|
32
src/innernetobjects/playercontrol.go
Normal file
32
src/innernetobjects/playercontrol.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PlayerControl struct {
|
||||||
|
IsNew bool
|
||||||
|
PlayerID byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (control *PlayerControl) Write(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
p := protocol.NewEmptyPacket()
|
||||||
|
if isSpawn {
|
||||||
|
p.WriteBool(control.IsNew)
|
||||||
|
p.Write(control.PlayerID)
|
||||||
|
h := protocol.NewHazelFromRawData(0, p.Dump())
|
||||||
|
h.WriteToPacket(packet)
|
||||||
|
} else {
|
||||||
|
p.Write(control.PlayerID)
|
||||||
|
p.Copy(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (control *PlayerControl) Read(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
p := packet
|
||||||
|
if isSpawn {
|
||||||
|
p = packet.ReadHazel().GetUnderlyingPacket()
|
||||||
|
control.IsNew = p.ReadBool()
|
||||||
|
}
|
||||||
|
control.PlayerID = p.Read()
|
||||||
|
}
|
35
src/innernetobjects/playernetworktransform.go
Normal file
35
src/innernetobjects/playernetworktransform.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PlayerNetworkTransform struct {
|
||||||
|
LastSequenceID uint16
|
||||||
|
TargetPosition util.Vec2
|
||||||
|
TargetVelocity util.Vec2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (transform *PlayerNetworkTransform) Write(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
p := protocol.NewEmptyPacket()
|
||||||
|
p.WriteUInt16(transform.LastSequenceID)
|
||||||
|
p.WriteVector2(transform.TargetPosition)
|
||||||
|
p.WriteVector2(transform.TargetVelocity)
|
||||||
|
if isSpawn {
|
||||||
|
h := protocol.NewHazelFromRawData(0, p.Dump())
|
||||||
|
h.WriteToPacket(packet)
|
||||||
|
} else {
|
||||||
|
p.Copy(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (transform *PlayerNetworkTransform) Read(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
p := packet
|
||||||
|
if isSpawn {
|
||||||
|
p = packet.ReadHazel().GetUnderlyingPacket()
|
||||||
|
}
|
||||||
|
transform.LastSequenceID = p.ReadUInt16()
|
||||||
|
transform.TargetPosition = p.ReadVector2()
|
||||||
|
transform.TargetVelocity = p.ReadVector2()
|
||||||
|
}
|
9
src/innernetobjects/playerphysics.go
Normal file
9
src/innernetobjects/playerphysics.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
// PlayerPhysics has no data
|
||||||
|
type PlayerPhysics struct{}
|
||||||
|
|
||||||
|
func (control *PlayerPhysics) Write(packet *protocol.Packet, isSpawn bool) {}
|
||||||
|
func (control *PlayerPhysics) Read(packet *protocol.Packet, isSpawn bool) {}
|
35
src/innernetobjects/polusshipstatus.go
Normal file
35
src/innernetobjects/polusshipstatus.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/systemtypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PolusShipStatus struct {
|
||||||
|
Systems map[int]*systemtypes.SystemType
|
||||||
|
SystemsMask uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPolusShipStatus() *MiraShipStatus {
|
||||||
|
a := &MiraShipStatus{}
|
||||||
|
a.Systems = make(map[int]*systemtypes.SystemType)
|
||||||
|
a.Systems[enum.SYSTEMTYPE_ELECTRICAL] = systemtypes.SystemTypeCast(&systemtypes.SwitchSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_MEDBAY] = systemtypes.SystemTypeCast(&systemtypes.MedScanSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_SECURITY] = systemtypes.SystemTypeCast(&systemtypes.SecurityCameraSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_COMMUNICATIONS] = systemtypes.SystemTypeCast(&systemtypes.HudOverrideSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_DOORS] = systemtypes.SystemTypeCast(&systemtypes.DoorsSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_DECONTAMINATION] = systemtypes.SystemTypeCast(&systemtypes.DeconSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_DECONTAMINATION_2] = systemtypes.SystemTypeCast(&systemtypes.DeconSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_SABOTAGE] = systemtypes.SystemTypeCast(&systemtypes.SabotageSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_LABORATORY] = systemtypes.SystemTypeCast(&systemtypes.ReactorSystem{})
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (polus *PolusShipStatus) Write(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
WriteShipStatus(polus.Systems, &polus.SystemsMask, packet, isSpawn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (polus *PolusShipStatus) Read(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
ReadShipStatus(polus.Systems, &polus.SystemsMask, packet, isSpawn)
|
||||||
|
}
|
50
src/innernetobjects/shipstatus.go
Normal file
50
src/innernetobjects/shipstatus.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/systemtypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WriteShipStatus(Systems map[int]*systemtypes.SystemType, SystemsMask *uint32, packet *protocol.Packet, isSpawn bool) {
|
||||||
|
p := protocol.NewEmptyPacket()
|
||||||
|
for i := 0; i < enum.TOTAL_SYSTEMTYPE; i++ {
|
||||||
|
if isSpawn {
|
||||||
|
if val, ok := Systems[i]; ok {
|
||||||
|
(*val).Write(p, isSpawn)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (*SystemsMask & (1 << i)) != 0 {
|
||||||
|
(*Systems[i]).Write(p, isSpawn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isSpawn {
|
||||||
|
h := protocol.NewHazelFromRawData(0, p.Dump())
|
||||||
|
h.WriteToPacket(packet)
|
||||||
|
} else {
|
||||||
|
packet.WritePackedUInt32(*SystemsMask)
|
||||||
|
p.Copy(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadShipStatus(Systems map[int]*systemtypes.SystemType, SystemsMask *uint32, packet *protocol.Packet, isSpawn bool) {
|
||||||
|
p := packet
|
||||||
|
if isSpawn {
|
||||||
|
p = packet.ReadHazel().GetUnderlyingPacket()
|
||||||
|
} else {
|
||||||
|
*SystemsMask = p.ReadPackedUInt32()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < enum.TOTAL_SYSTEMTYPE; i++ {
|
||||||
|
if isSpawn {
|
||||||
|
if val, ok := Systems[i]; ok {
|
||||||
|
(*val).Read(p, isSpawn)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (*SystemsMask & (1 << i)) != 0 {
|
||||||
|
(*Systems[i]).Read(p, isSpawn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
src/innernetobjects/skeldshipstatus.go
Normal file
34
src/innernetobjects/skeldshipstatus.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/systemtypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SkeldShipStatus struct {
|
||||||
|
Systems map[int]*systemtypes.SystemType
|
||||||
|
SystemsMask uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSkeldShipStatus() *SkeldShipStatus {
|
||||||
|
a := &SkeldShipStatus{}
|
||||||
|
a.Systems = make(map[int]*systemtypes.SystemType)
|
||||||
|
a.Systems[enum.SYSTEMTYPE_REACTOR] = systemtypes.SystemTypeCast(&systemtypes.ReactorSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_ELECTRICAL] = systemtypes.SystemTypeCast(&systemtypes.SwitchSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_O2] = systemtypes.SystemTypeCast(&systemtypes.LifeSuppSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_MEDBAY] = systemtypes.SystemTypeCast(&systemtypes.MedScanSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_SECURITY] = systemtypes.SystemTypeCast(&systemtypes.SecurityCameraSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_COMMUNICATIONS] = systemtypes.SystemTypeCast(&systemtypes.HudOverrideSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_DOORS] = systemtypes.SystemTypeCast(&systemtypes.AutoDoorsSystem{})
|
||||||
|
a.Systems[enum.SYSTEMTYPE_SABOTAGE] = systemtypes.SystemTypeCast(&systemtypes.SabotageSystem{})
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (skeld *SkeldShipStatus) Write(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
WriteShipStatus(skeld.Systems, &skeld.SystemsMask, packet, isSpawn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (skeld *SkeldShipStatus) Read(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
ReadShipStatus(skeld.Systems, &skeld.SystemsMask, packet, isSpawn)
|
||||||
|
}
|
46
src/innernetobjects/votebansystem.go
Normal file
46
src/innernetobjects/votebansystem.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package innernetobjects
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VoteBanSystem struct {
|
||||||
|
VotedPlayers []*VoteBanItem
|
||||||
|
}
|
||||||
|
|
||||||
|
type VoteBanItem struct {
|
||||||
|
Player uint32
|
||||||
|
Votes [3]uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ban *VoteBanSystem) Write(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
p := protocol.NewEmptyPacket()
|
||||||
|
p.Write(byte(len(ban.VotedPlayers)))
|
||||||
|
for i := 0; i < len(ban.VotedPlayers); i++ {
|
||||||
|
p.WriteUInt32(ban.VotedPlayers[i].Player)
|
||||||
|
for j := 0; j < 3; j++ {
|
||||||
|
p.WritePackedUInt32(ban.VotedPlayers[i].Votes[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isSpawn {
|
||||||
|
h := protocol.NewHazelFromRawData(0, p.Dump())
|
||||||
|
h.WriteToPacket(packet)
|
||||||
|
} else {
|
||||||
|
p.Copy(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ban *VoteBanSystem) Read(packet *protocol.Packet, isSpawn bool) {
|
||||||
|
p := packet
|
||||||
|
if isSpawn {
|
||||||
|
p = packet.ReadHazel().GetUnderlyingPacket()
|
||||||
|
}
|
||||||
|
|
||||||
|
ban.VotedPlayers = make([]*VoteBanItem, p.Read())
|
||||||
|
for i := 0; i < len(ban.VotedPlayers); i++ {
|
||||||
|
ban.VotedPlayers[i].Player = p.ReadUInt32()
|
||||||
|
for j := 0; j < 3; j++ {
|
||||||
|
ban.VotedPlayers[i].Votes[j] = p.ReadPackedUInt32()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/mapdata/go.mod
Normal file
10
src/mapdata/go.mod
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module codehub.onpointcoding.net/sean/go-susapp/mapdata
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
replace (
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/protocol => ../protocol
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/util => ../util
|
||||||
|
)
|
||||||
|
|
||||||
|
require codehub.onpointcoding.net/sean/go-susapp/util v1.0.0
|
16
src/mapdata/lobby.go
Normal file
16
src/mapdata/lobby.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package mapdata
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/util"
|
||||||
|
|
||||||
|
var LobbySpawnPositions = []util.Vec2{
|
||||||
|
util.NewVec2(-1.6, 2.4),
|
||||||
|
util.NewVec2(-1.3, 2.5),
|
||||||
|
util.NewVec2(-1.1, 2.5),
|
||||||
|
util.NewVec2(-0.8, 2.6),
|
||||||
|
util.NewVec2(-0.6, 2.7),
|
||||||
|
util.NewVec2(0.7, 2.8),
|
||||||
|
util.NewVec2(0.9, 2.6),
|
||||||
|
util.NewVec2(1.1, 2.6),
|
||||||
|
util.NewVec2(1.4, 2.6),
|
||||||
|
util.NewVec2(1.7, 2.4),
|
||||||
|
}
|
24
src/packets/00_hostgameC2S.go
Normal file
24
src/packets/00_hostgameC2S.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HostGameC2S struct {
|
||||||
|
Options *protocol.GameOptionsData
|
||||||
|
QuickChatMode byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *HostGameC2S) TypeCode() byte {
|
||||||
|
return 0x00
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *HostGameC2S) Write(packet *protocol.Packet) {
|
||||||
|
d.Options.Write(packet)
|
||||||
|
packet.Write(d.QuickChatMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *HostGameC2S) Read(packet *protocol.Packet) {
|
||||||
|
d.Options = protocol.NewGameOptionsDataFromPacket(packet)
|
||||||
|
d.QuickChatMode = packet.Read()
|
||||||
|
}
|
19
src/packets/00_hostgameS2C.go
Normal file
19
src/packets/00_hostgameS2C.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type HostGameS2C struct {
|
||||||
|
GameID int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *HostGameS2C) TypeCode() int {
|
||||||
|
return 0x00
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *HostGameS2C) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *HostGameS2C) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
}
|
19
src/packets/01_joingameC2S.go
Normal file
19
src/packets/01_joingameC2S.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type JoinGameC2S struct {
|
||||||
|
GameID int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinGameC2S) TypeCode() byte {
|
||||||
|
return 0x01
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinGameC2S) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinGameC2S) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
}
|
19
src/packets/01_joingameS2C.go
Normal file
19
src/packets/01_joingameS2C.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type JoinGameS2C struct {
|
||||||
|
DisconnectReason int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinGameS2C) TypeCode() byte {
|
||||||
|
return 0x01
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinGameS2C) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.DisconnectReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinGameS2C) Read(packet *protocol.Packet) {
|
||||||
|
d.DisconnectReason = packet.ReadInt32()
|
||||||
|
}
|
25
src/packets/01_joingameS2G.go
Normal file
25
src/packets/01_joingameS2G.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type JoinGameS2G struct {
|
||||||
|
GameID int32
|
||||||
|
JoiningClientID uint32
|
||||||
|
HostClientID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinGameS2G) TypeCode() byte {
|
||||||
|
return 0x01
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinGameS2G) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.WriteUInt32(d.JoiningClientID)
|
||||||
|
packet.WriteUInt32(d.HostClientID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinGameS2G) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.JoiningClientID = packet.ReadUInt32()
|
||||||
|
d.HostClientID = packet.ReadUInt32()
|
||||||
|
}
|
19
src/packets/02_startgameH2G.go
Normal file
19
src/packets/02_startgameH2G.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
type StartGameH2G struct {
|
||||||
|
GameID int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *StartGameH2G) TypeCode() byte {
|
||||||
|
return 0x02
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *StartGameH2G) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *StartGameH2G) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
}
|
22
src/packets/03_removegameS2C.go
Normal file
22
src/packets/03_removegameS2C.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RemoveGameS2C struct {
|
||||||
|
DisconnectReason byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RemoveGameS2C) TypeCode() byte {
|
||||||
|
return 0x03
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RemoveGameS2C) Write(packet *protocol.Packet) {
|
||||||
|
packet.Write(d.DisconnectReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RemoveGameS2C) Read(packet *protocol.Packet) {
|
||||||
|
d.DisconnectReason = packet.ReadDefault(enum.DISCONNECT_SERVER_REQUEST)
|
||||||
|
}
|
28
src/packets/04_removeplayerH2C.go
Normal file
28
src/packets/04_removeplayerH2C.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RemovePlayerH2C struct {
|
||||||
|
GameID int32
|
||||||
|
DisconnectedClientID uint32
|
||||||
|
DisconnectReason byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RemovePlayerH2C) TypeCode() byte {
|
||||||
|
return 0x04
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RemovePlayerH2C) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.WritePackedUInt32(d.DisconnectedClientID)
|
||||||
|
packet.Write(d.DisconnectReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RemovePlayerH2C) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.DisconnectedClientID = packet.ReadPackedUInt32()
|
||||||
|
d.DisconnectReason = packet.ReadDefault(enum.DISCONNECT_SERVER_REQUEST)
|
||||||
|
}
|
31
src/packets/04_removeplayerS2G.go
Normal file
31
src/packets/04_removeplayerS2G.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/enum"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RemovePlayerS2G struct {
|
||||||
|
GameID int32
|
||||||
|
DisconnectedClientID uint32
|
||||||
|
HostClientID uint32
|
||||||
|
DisconnectReason byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RemovePlayerS2G) TypeCode() byte {
|
||||||
|
return 0x04
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RemovePlayerS2G) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.WriteUInt32(d.DisconnectedClientID)
|
||||||
|
packet.WriteUInt32(d.HostClientID)
|
||||||
|
packet.Write(d.DisconnectReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RemovePlayerS2G) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.DisconnectedClientID = packet.ReadUInt32()
|
||||||
|
d.HostClientID = packet.ReadUInt32()
|
||||||
|
d.DisconnectReason = packet.ReadDefault(enum.DISCONNECT_SERVER_REQUEST)
|
||||||
|
}
|
36
src/packets/05_gamedataall.go
Normal file
36
src/packets/05_gamedataall.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GameDataAll struct {
|
||||||
|
GameID int32
|
||||||
|
Subpackets []*protocol.Hazel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGameDataSingleSubpacket(GameID int32, h *GameDataSubpacket) *GameDataAll {
|
||||||
|
return &GameDataAll{
|
||||||
|
GameID,
|
||||||
|
[]*protocol.Hazel{(*h).AsHazel()},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GameDataAll) TypeCode() byte { return 0x05 }
|
||||||
|
func (d *GameDataAll) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
for i := 0; i < len(d.Subpackets); i++ {
|
||||||
|
d.Subpackets[i].WriteToPacket(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (d *GameDataAll) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
for packet.Remaining() > 0 {
|
||||||
|
a := protocol.NewHazel(packet)
|
||||||
|
d.Subpackets = append(d.Subpackets, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GameDataSubpacket interface {
|
||||||
|
AsHazel() *protocol.Hazel
|
||||||
|
}
|
38
src/packets/06_gamedatato.go
Normal file
38
src/packets/06_gamedatato.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GameDataTo struct {
|
||||||
|
GameID int32
|
||||||
|
TargetClientID uint32
|
||||||
|
Subpackets []*protocol.Hazel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGameDataToSingleSubpacket(GameID int32, TargetClientID uint32, h *GameDataSubpacket) *GameDataTo {
|
||||||
|
return &GameDataTo{
|
||||||
|
GameID,
|
||||||
|
TargetClientID,
|
||||||
|
[]*protocol.Hazel{(*h).AsHazel()},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GameDataTo) TypeCode() byte { return 0x06 }
|
||||||
|
|
||||||
|
func (d *GameDataTo) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.WritePackedUInt32(d.TargetClientID)
|
||||||
|
for i := 0; i < len(d.Subpackets); i++ {
|
||||||
|
d.Subpackets[i].WriteToPacket(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GameDataTo) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.TargetClientID = packet.ReadPackedUInt32()
|
||||||
|
for packet.Remaining() > 0 {
|
||||||
|
a := protocol.NewHazel(packet)
|
||||||
|
d.Subpackets = append(d.Subpackets, a)
|
||||||
|
}
|
||||||
|
}
|
37
src/packets/07_joinedgameH2C.go
Normal file
37
src/packets/07_joinedgameH2C.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JoinedGameH2C struct {
|
||||||
|
GameID int32
|
||||||
|
JoinedClientID uint32
|
||||||
|
HostClientID uint32
|
||||||
|
OtherClientIDs []uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinedGameH2C) TypeCode() byte {
|
||||||
|
return 0x07
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinedGameH2C) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.WriteUInt32(d.JoinedClientID)
|
||||||
|
packet.WriteUInt32(d.HostClientID)
|
||||||
|
packet.WritePackedUInt32(uint32(len(d.OtherClientIDs)))
|
||||||
|
for i := 0; i < len(d.OtherClientIDs); i++ {
|
||||||
|
packet.WritePackedUInt32(d.OtherClientIDs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *JoinedGameH2C) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.JoinedClientID = packet.ReadUInt32()
|
||||||
|
d.HostClientID = packet.ReadUInt32()
|
||||||
|
l := int(packet.ReadUInt32())
|
||||||
|
d.OtherClientIDs = make([]uint32, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
d.OtherClientIDs[i] = packet.ReadUInt32()
|
||||||
|
}
|
||||||
|
}
|
27
src/packets/08_endgameH2G.go
Normal file
27
src/packets/08_endgameH2G.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EndGameH2G struct {
|
||||||
|
GameID int32
|
||||||
|
GameOverReason byte
|
||||||
|
ShowAd bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *EndGameH2G) TypeCode() byte {
|
||||||
|
return 0x08
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *EndGameH2G) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.Write(d.GameOverReason)
|
||||||
|
packet.WriteBool(d.ShowAd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *EndGameH2G) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.GameOverReason = packet.Read()
|
||||||
|
d.ShowAd = packet.ReadBool()
|
||||||
|
}
|
5
src/packets/09_getgamelist.go
Normal file
5
src/packets/09_getgamelist.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
// GetGameListAll is a legacy packet
|
||||||
|
type GetGameListAll struct {
|
||||||
|
}
|
27
src/packets/10_altergame.go
Normal file
27
src/packets/10_altergame.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AlterGameH2G struct {
|
||||||
|
GameID int32
|
||||||
|
TagID byte
|
||||||
|
TagValue byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *AlterGameH2G) TypeCode() byte {
|
||||||
|
return 0x0a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *AlterGameH2G) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.Write(d.TagID)
|
||||||
|
packet.Write(d.TagValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *AlterGameH2G) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.TagID = packet.Read()
|
||||||
|
d.TagValue = packet.Read()
|
||||||
|
}
|
30
src/packets/11_kickplayer.go
Normal file
30
src/packets/11_kickplayer.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KickPlayerH2G struct {
|
||||||
|
GameID int32
|
||||||
|
KickedClientID uint32
|
||||||
|
IsBanned bool
|
||||||
|
DisconnectReason byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *KickPlayerH2G) TypeCode() byte {
|
||||||
|
return 0x0b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *KickPlayerH2G) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.WritePackedUInt32(d.KickedClientID)
|
||||||
|
packet.WriteBool(d.IsBanned)
|
||||||
|
packet.Write(d.DisconnectReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *KickPlayerH2G) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.KickedClientID = packet.ReadPackedUInt32()
|
||||||
|
d.IsBanned = packet.ReadBool()
|
||||||
|
d.DisconnectReason = packet.Read()
|
||||||
|
}
|
24
src/packets/12_waitforhostC2H.go
Normal file
24
src/packets/12_waitforhostC2H.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WaitForHostC2H struct {
|
||||||
|
GameID int32
|
||||||
|
RejoiningClientID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *WaitForHostC2H) TypeCode() byte {
|
||||||
|
return 0x0c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *WaitForHostC2H) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.WriteUInt32(d.RejoiningClientID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *WaitForHostC2H) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.RejoiningClientID = packet.ReadUInt32()
|
||||||
|
}
|
26
src/packets/13_redirect.go
Normal file
26
src/packets/13_redirect.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RedirectS2C struct {
|
||||||
|
IPAddress net.IP
|
||||||
|
Port uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RedirectS2C) TypeCode() byte {
|
||||||
|
return 0x0d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RedirectS2C) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteIP(d.IPAddress)
|
||||||
|
packet.WriteUInt16(d.Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RedirectS2C) Read(packet *protocol.Packet) {
|
||||||
|
d.IPAddress = packet.ReadIP()
|
||||||
|
d.Port = packet.ReadUInt16()
|
||||||
|
}
|
42
src/packets/14_reselectserverS2C.go
Normal file
42
src/packets/14_reselectserverS2C.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ReselectServerS2C struct {
|
||||||
|
Version byte
|
||||||
|
MasterServers []*util.MasterServer
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentReselectServerVerion byte = 1
|
||||||
|
|
||||||
|
func (d *ReselectServerS2C) TypeCode() byte {
|
||||||
|
return 0x0e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReselectServerS2C) Write(packet *protocol.Packet) {
|
||||||
|
packet.Write(currentReselectServerVerion)
|
||||||
|
packet.WritePackedUInt32(uint32(len(d.MasterServers)))
|
||||||
|
for i := 0; i < len(d.MasterServers); i++ {
|
||||||
|
packet.WriteString(d.MasterServers[i].Name)
|
||||||
|
packet.WriteIP(d.MasterServers[i].IPAddress)
|
||||||
|
packet.WriteUInt16(d.MasterServers[i].Port)
|
||||||
|
packet.WritePackedUInt32(d.MasterServers[i].NumberOfConnections)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReselectServerS2C) Read(packet *protocol.Packet) {
|
||||||
|
d.Version = packet.Read()
|
||||||
|
l := int(packet.ReadPackedUInt32())
|
||||||
|
d.MasterServers = make([]*util.MasterServer, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
d.MasterServers[i] = &util.MasterServer{
|
||||||
|
Name: packet.ReadString(),
|
||||||
|
IPAddress: packet.ReadIP(),
|
||||||
|
Port: packet.ReadUInt16(),
|
||||||
|
NumberOfConnections: packet.ReadPackedUInt32(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
src/packets/16_GetGameListV2C2S.go
Normal file
29
src/packets/16_GetGameListV2C2S.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetGameListV2C2S struct {
|
||||||
|
Unknown02 int32
|
||||||
|
Options *protocol.GameOptionsData
|
||||||
|
QuickChatMode byte
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentUnknown02Value int32 = 0x02
|
||||||
|
|
||||||
|
func (d *GetGameListV2C2S) TypeCode() byte {
|
||||||
|
return 0x10
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GetGameListV2C2S) Write(packet *protocol.Packet) {
|
||||||
|
packet.WritePackedInt32(currentUnknown02Value)
|
||||||
|
d.Options.Write(packet)
|
||||||
|
packet.Write(d.QuickChatMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GetGameListV2C2S) Read(packet *protocol.Packet) {
|
||||||
|
d.Unknown02 = packet.ReadInt32()
|
||||||
|
d.Options = protocol.NewGameOptionsDataFromPacket(packet)
|
||||||
|
d.QuickChatMode = packet.Read()
|
||||||
|
}
|
30
src/packets/16_GetGameListV2S2C.go
Normal file
30
src/packets/16_GetGameListV2S2C.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetGameListV2S2C struct {
|
||||||
|
GameCounts *protocol.Hazel // tag = 0x01
|
||||||
|
GameList *protocol.Hazel // tag = 0x00
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GetGameListV2S2C) TypeCode() byte {
|
||||||
|
return 0x10
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GetGameListV2S2C) Write(packet *protocol.Packet) {
|
||||||
|
d.GameCounts.WriteToPacket(packet)
|
||||||
|
d.GameList.WriteToPacket(packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GetGameListV2S2C) Read(packet *protocol.Packet) {
|
||||||
|
for packet.Remaining() > 0 {
|
||||||
|
h := packet.ReadHazel()
|
||||||
|
if h.GetTag() == 0x01 {
|
||||||
|
d.GameCounts = h
|
||||||
|
} else if h.GetTag() == 0x00 {
|
||||||
|
d.GameList = h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
src/packets/17_reportplayerC2S.go
Normal file
27
src/packets/17_reportplayerC2S.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ReportPlayerC2S struct {
|
||||||
|
GameID int32
|
||||||
|
ReportedClientID uint32
|
||||||
|
ReportReason byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReportPlayerC2S) TypeCode() byte {
|
||||||
|
return 0x11
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReportPlayerC2S) Write(packet *protocol.Packet) {
|
||||||
|
packet.WriteInt32(d.GameID)
|
||||||
|
packet.WritePackedUInt32(d.ReportedClientID)
|
||||||
|
packet.Write(d.ReportReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReportPlayerC2S) Read(packet *protocol.Packet) {
|
||||||
|
d.GameID = packet.ReadInt32()
|
||||||
|
d.ReportedClientID = packet.ReadPackedUInt32()
|
||||||
|
d.ReportReason = packet.Read()
|
||||||
|
}
|
30
src/packets/17_reportplayerS2C.go
Normal file
30
src/packets/17_reportplayerS2C.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ReportPlayerS2C struct {
|
||||||
|
ReportedClientID uint32
|
||||||
|
ReportReason uint32
|
||||||
|
ReportOutcome byte
|
||||||
|
ReportedPlayerName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReportPlayerS2C) TypeCode() byte {
|
||||||
|
return 0x11
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReportPlayerS2C) Write(packet *protocol.Packet) {
|
||||||
|
packet.WritePackedUInt32(d.ReportedClientID)
|
||||||
|
packet.WriteUInt32(d.ReportReason)
|
||||||
|
packet.Write(d.ReportOutcome)
|
||||||
|
packet.WriteString(d.ReportedPlayerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ReportPlayerS2C) Read(packet *protocol.Packet) {
|
||||||
|
d.ReportedClientID = packet.ReadPackedUInt32()
|
||||||
|
d.ReportReason = packet.ReadUInt32()
|
||||||
|
d.ReportOutcome = packet.Read()
|
||||||
|
d.ReportedPlayerName = packet.ReadString()
|
||||||
|
}
|
16
src/packets/gamepacket.go
Normal file
16
src/packets/gamepacket.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package packets
|
||||||
|
|
||||||
|
import "codehub.onpointcoding.net/sean/go-susapp/protocol"
|
||||||
|
|
||||||
|
// PacketBase PacketType
|
||||||
|
|
||||||
|
// C2S = client to server
|
||||||
|
// S2C = server to client
|
||||||
|
// S2G = server to game (broadcast to all clients from the server)
|
||||||
|
// H2G = host to game (broadcast to all clients from the host)
|
||||||
|
|
||||||
|
type GamePacket interface {
|
||||||
|
Write(packet *protocol.Packet)
|
||||||
|
Read(packet *protocol.Packet)
|
||||||
|
TypeCode() byte
|
||||||
|
}
|
15
src/packets/go.mod
Normal file
15
src/packets/go.mod
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module codehub.onpointcoding.net/sean/go-susapp/packets
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
replace (
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/enum => ../enum
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/protocol => ../protocol
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/util => ../util
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/enum v1.0.0
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/protocol v1.0.0
|
||||||
|
codehub.onpointcoding.net/sean/go-susapp/util v1.0.0
|
||||||
|
)
|
60
src/protocol/gamelist.go
Normal file
60
src/protocol/gamelist.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GameList struct {
|
||||||
|
Games []GameListItem
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGameList(packet *Packet) *GameList {
|
||||||
|
games := make([]GameListItem, 0)
|
||||||
|
for packet.Remaining() > 0 {
|
||||||
|
games = append(games, *NewGameListItem(packet))
|
||||||
|
}
|
||||||
|
return &GameList{games}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *GameList) WriteToPacket(packet *Packet) {
|
||||||
|
for i := 0; i < len(list.Games); i++ {
|
||||||
|
list.Games[i].WriteToPacket(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GameListItem struct {
|
||||||
|
IPAddress net.IP
|
||||||
|
Port uint16
|
||||||
|
GameID int32
|
||||||
|
HostPlayer string
|
||||||
|
NumberOfPlayers byte
|
||||||
|
Age uint32
|
||||||
|
MapID byte
|
||||||
|
NumberOfImpostors byte
|
||||||
|
MaxNumberOfPlayers byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGameListItem(packet *Packet) *GameListItem {
|
||||||
|
ip := packet.ReadIP()
|
||||||
|
port := packet.ReadUInt16()
|
||||||
|
gameId := packet.ReadInt32()
|
||||||
|
hostPlayer := packet.ReadString()
|
||||||
|
numberOfPlayers := packet.Read()
|
||||||
|
age := packet.ReadPackedUInt32()
|
||||||
|
mapId := packet.Read()
|
||||||
|
numberOfImpostors := packet.Read()
|
||||||
|
maxNumberOfPlayers := packet.Read()
|
||||||
|
return &GameListItem{ip, port, gameId, hostPlayer, numberOfPlayers, age, mapId, numberOfImpostors, maxNumberOfPlayers}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (item *GameListItem) WriteToPacket(packet *Packet) {
|
||||||
|
packet.WriteIP(item.IPAddress)
|
||||||
|
packet.WriteUInt16(item.Port)
|
||||||
|
packet.WriteInt32(item.GameID)
|
||||||
|
packet.WriteString(item.HostPlayer)
|
||||||
|
packet.Write(item.NumberOfPlayers)
|
||||||
|
packet.WritePackedUInt32(item.Age)
|
||||||
|
packet.Write(item.MapID)
|
||||||
|
packet.Write(item.NumberOfImpostors)
|
||||||
|
packet.Write(item.MaxNumberOfPlayers)
|
||||||
|
}
|
96
src/protocol/gameoptionsdata.go
Normal file
96
src/protocol/gameoptionsdata.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
type GameOptionsData struct {
|
||||||
|
Version byte
|
||||||
|
MaxNumberOfPlayers byte
|
||||||
|
Keywords uint32
|
||||||
|
Maps byte
|
||||||
|
PlayerSpeedModifier float32
|
||||||
|
CrewmateLightModifier float32
|
||||||
|
ImpostorLightModifier float32
|
||||||
|
KillCooldown float32
|
||||||
|
NumberOfCommonTasks byte
|
||||||
|
NumberOfLongTasks byte
|
||||||
|
NumberOfShortTasks byte
|
||||||
|
NumberOfEmergencyMeetings uint32
|
||||||
|
NumberOfImpostors byte
|
||||||
|
KillDistance byte
|
||||||
|
DiscussionTime uint32
|
||||||
|
VotingTime uint32
|
||||||
|
IsDefaults bool
|
||||||
|
EmergencyCooldown byte
|
||||||
|
ConfirmEjects bool
|
||||||
|
VisualTasks bool
|
||||||
|
AnonymousVotes bool
|
||||||
|
TaskBarUpdates byte
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentGameOptionsVersion byte = 4
|
||||||
|
|
||||||
|
// Create new default options
|
||||||
|
func NewDefaultGameOptionsData() *GameOptionsData {
|
||||||
|
return &GameOptionsData{currentGameOptionsVersion, 10, 1, 1, 1, 1, 1.5, 45, 1, 1, 2, 1, 1, 1, 15, 120, true, 15, true, true, false, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new options from packet data
|
||||||
|
func NewGameOptionsDataFromPacket(packet *Packet) *GameOptionsData {
|
||||||
|
a := NewDefaultGameOptionsData()
|
||||||
|
a.Read(packet)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *GameOptionsData) Write(packet *Packet) {
|
||||||
|
p := NewEmptyPacket()
|
||||||
|
p.Write(data.Version)
|
||||||
|
p.Write(data.MaxNumberOfPlayers)
|
||||||
|
p.WriteUInt32(data.Keywords)
|
||||||
|
p.Write(data.Maps)
|
||||||
|
p.WriteFloat(data.PlayerSpeedModifier)
|
||||||
|
p.WriteFloat(data.CrewmateLightModifier)
|
||||||
|
p.WriteFloat(data.ImpostorLightModifier)
|
||||||
|
p.WriteFloat(data.KillCooldown)
|
||||||
|
p.Write(data.NumberOfCommonTasks)
|
||||||
|
p.Write(data.NumberOfLongTasks)
|
||||||
|
p.Write(data.NumberOfShortTasks)
|
||||||
|
p.WritePackedUInt32(data.NumberOfEmergencyMeetings)
|
||||||
|
p.Write(data.NumberOfImpostors)
|
||||||
|
p.Write(data.KillDistance)
|
||||||
|
p.WriteUInt32(data.DiscussionTime)
|
||||||
|
p.WriteUInt32(data.VotingTime)
|
||||||
|
p.WriteBool(data.IsDefaults)
|
||||||
|
p.Write(data.EmergencyCooldown)
|
||||||
|
p.WriteBool(data.ConfirmEjects)
|
||||||
|
p.WriteBool(data.VisualTasks)
|
||||||
|
p.WriteBool(data.AnonymousVotes)
|
||||||
|
p.Write(data.TaskBarUpdates)
|
||||||
|
packet.WritePackedUInt32(uint32(p.Size()))
|
||||||
|
p.Copy(packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *GameOptionsData) Read(packet *Packet) {
|
||||||
|
l := packet.ReadPackedUInt32()
|
||||||
|
p := NewPacket(packet.ReadBytes(int(l)))
|
||||||
|
|
||||||
|
data.Version = p.Read()
|
||||||
|
data.MaxNumberOfPlayers = p.Read()
|
||||||
|
data.Keywords = p.ReadUInt32()
|
||||||
|
data.Maps = p.Read()
|
||||||
|
data.PlayerSpeedModifier = p.ReadFloat()
|
||||||
|
data.CrewmateLightModifier = p.ReadFloat()
|
||||||
|
data.ImpostorLightModifier = p.ReadFloat()
|
||||||
|
data.KillCooldown = p.ReadFloat()
|
||||||
|
data.NumberOfCommonTasks = p.Read()
|
||||||
|
data.NumberOfLongTasks = p.Read()
|
||||||
|
data.NumberOfShortTasks = p.Read()
|
||||||
|
data.NumberOfEmergencyMeetings = p.ReadPackedUInt32()
|
||||||
|
data.NumberOfImpostors = p.Read()
|
||||||
|
data.KillDistance = p.Read()
|
||||||
|
data.DiscussionTime = p.ReadUInt32()
|
||||||
|
data.VotingTime = p.ReadUInt32()
|
||||||
|
data.IsDefaults = p.ReadBool()
|
||||||
|
data.EmergencyCooldown = p.ReadDefault(15)
|
||||||
|
data.ConfirmEjects = p.ReadBoolDefault(true)
|
||||||
|
data.VisualTasks = p.ReadBoolDefault(true)
|
||||||
|
data.AnonymousVotes = p.ReadBoolDefault(false)
|
||||||
|
data.TaskBarUpdates = p.ReadDefault(0)
|
||||||
|
}
|
6
src/protocol/go.mod
Normal file
6
src/protocol/go.mod
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module codehub.onpointcoding.net/sean/go-susapp/protocol
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
replace codehub.onpointcoding.net/sean/go-susapp/util => ../util
|
||||||
|
require codehub.onpointcoding.net/sean/go-susapp/util v1.0.0
|
59
src/protocol/hazelmessage.go
Normal file
59
src/protocol/hazelmessage.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
type Hazel struct {
|
||||||
|
p *Packet
|
||||||
|
l uint16
|
||||||
|
t byte
|
||||||
|
payload *HazelPayload
|
||||||
|
readPacket bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHazel(packet *Packet) *Hazel {
|
||||||
|
l := packet.ReadUInt16()
|
||||||
|
t := packet.Read()
|
||||||
|
p := NewPacket(packet.ReadBytes(int(l)))
|
||||||
|
return &Hazel{p, l, t, nil, true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHazelFromPayload(payload *HazelPayload) *Hazel {
|
||||||
|
p := NewEmptyPacket()
|
||||||
|
return &Hazel{p, 0, (*payload).TypeCode(), payload, false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHazelFromRawData(tag byte, b []byte) *Hazel {
|
||||||
|
p := NewEmptyPacket()
|
||||||
|
p.WriteBytes(b)
|
||||||
|
return &Hazel{p, 0, tag, nil, true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hazel *Hazel) WriteToPacket(packet *Packet) {
|
||||||
|
if hazel.readPacket {
|
||||||
|
packet.WriteUInt16(hazel.l)
|
||||||
|
packet.Write(hazel.t)
|
||||||
|
hazel.p.Copy(packet)
|
||||||
|
} else {
|
||||||
|
p := NewEmptyPacket()
|
||||||
|
(*hazel.payload).Write(p)
|
||||||
|
packet.WriteUInt16(uint16(p.Size()))
|
||||||
|
packet.Write((*hazel.payload).TypeCode())
|
||||||
|
p.Copy(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hazel *Hazel) GetUnderlyingPacket() *Packet {
|
||||||
|
return hazel.p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hazel *Hazel) Length() uint16 {
|
||||||
|
return hazel.l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hazel *Hazel) GetTag() byte {
|
||||||
|
return hazel.t
|
||||||
|
}
|
||||||
|
|
||||||
|
type HazelPayload interface {
|
||||||
|
Write(packet *Packet)
|
||||||
|
Read(packet *Packet)
|
||||||
|
TypeCode() byte
|
||||||
|
}
|
29
src/protocol/netcomponent.go
Normal file
29
src/protocol/netcomponent.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
type SpawnComponent struct {
|
||||||
|
NetID uint32
|
||||||
|
ComponentData *Hazel
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *SpawnComponent) Write(packet *Packet) {
|
||||||
|
packet.WritePackedUInt32(d.NetID)
|
||||||
|
d.ComponentData.WriteToPacket(packet)
|
||||||
|
}
|
||||||
|
func (d *SpawnComponent) Read(packet *Packet) {
|
||||||
|
d.NetID = packet.ReadPackedUInt32()
|
||||||
|
d.ComponentData = NewHazel(packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateComponent struct {
|
||||||
|
NetID uint32
|
||||||
|
RawData *Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *UpdateComponent) Write(packet *Packet) {
|
||||||
|
packet.WritePackedUInt32(d.NetID)
|
||||||
|
d.RawData.Copy(packet)
|
||||||
|
}
|
||||||
|
func (d *UpdateComponent) Read(packet *Packet) {
|
||||||
|
d.NetID = packet.ReadPackedUInt32()
|
||||||
|
d.RawData = packet
|
||||||
|
}
|
241
src/protocol/packet.go
Normal file
241
src/protocol/packet.go
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"math"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"codehub.onpointcoding.net/sean/go-susapp/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Packet struct {
|
||||||
|
data []byte
|
||||||
|
idx int
|
||||||
|
l int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPacket(d []byte) *Packet {
|
||||||
|
return &Packet{
|
||||||
|
data: d,
|
||||||
|
l: len(d),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEmptyPacket() *Packet {
|
||||||
|
return &Packet{
|
||||||
|
data: []byte{},
|
||||||
|
l: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) Seek(v int) {
|
||||||
|
packet.idx = v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) Size() int {
|
||||||
|
return len(packet.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) Dump() []byte {
|
||||||
|
return packet.data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) Remaining() int {
|
||||||
|
return packet.Size() - packet.idx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) Copy(p *Packet) {
|
||||||
|
p.WriteBytes(packet.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) Read() byte {
|
||||||
|
return packet.ReadDefault(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadDefault(d byte) byte {
|
||||||
|
if packet.idx >= len(packet.data) {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
v := packet.data[packet.idx]
|
||||||
|
packet.idx++
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) Write(v byte) {
|
||||||
|
packet.data = append(packet.data, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadBytes(n int) []byte {
|
||||||
|
b := make([]byte, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
b[i] = packet.Read()
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteBytes(v []byte) {
|
||||||
|
packet.data = append(packet.data, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadInt16() int16 {
|
||||||
|
return int16(packet.ReadUInt16())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteInt16(v int16) {
|
||||||
|
packet.WriteUInt16(uint16(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadUInt16() uint16 {
|
||||||
|
return binary.LittleEndian.Uint16(packet.ReadBytes(2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteUInt16(v uint16) {
|
||||||
|
var b [2]byte
|
||||||
|
binary.LittleEndian.PutUint16(b[:], v)
|
||||||
|
packet.WriteBytes(b[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadUInt16BigEndian() uint16 {
|
||||||
|
return binary.BigEndian.Uint16(packet.ReadBytes(2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteUInt16BigEndian(v uint16) {
|
||||||
|
var b [2]byte
|
||||||
|
binary.BigEndian.PutUint16(b[:], v)
|
||||||
|
packet.WriteBytes(b[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadInt32() int32 {
|
||||||
|
return int32(packet.ReadUInt32())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteInt32(v int32) {
|
||||||
|
packet.WriteUInt32(uint32(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadUInt32() uint32 {
|
||||||
|
return binary.LittleEndian.Uint32(packet.ReadBytes(4))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteUInt32(v uint32) {
|
||||||
|
var b [4]byte
|
||||||
|
binary.LittleEndian.PutUint32(b[:], v)
|
||||||
|
packet.WriteBytes(b[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadFloat() float32 {
|
||||||
|
return math.Float32frombits(packet.ReadUInt32())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteFloat(v float32) {
|
||||||
|
var b [4]byte
|
||||||
|
binary.LittleEndian.PutUint32(b[:], math.Float32bits(v))
|
||||||
|
packet.WriteBytes(b[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadBool() bool {
|
||||||
|
return packet.Read() == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadBoolDefault(v bool) bool {
|
||||||
|
if v {
|
||||||
|
return packet.ReadDefault(1) == 1
|
||||||
|
} else {
|
||||||
|
return packet.ReadDefault(0) == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteBool(v bool) {
|
||||||
|
if v {
|
||||||
|
packet.Write(1)
|
||||||
|
} else {
|
||||||
|
packet.Write(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ParsePackedInt32() int32 {
|
||||||
|
return int32(packet.ReadPackedUInt32())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WritePackedInt32(v int32) {
|
||||||
|
packet.WritePackedUInt32(uint32(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadPackedUInt32() uint32 {
|
||||||
|
readMore := true
|
||||||
|
shift := 0
|
||||||
|
var output uint32 = 0
|
||||||
|
|
||||||
|
for readMore {
|
||||||
|
b := packet.Read()
|
||||||
|
if b > 0x80 {
|
||||||
|
readMore = true
|
||||||
|
b ^= 0x80
|
||||||
|
} else {
|
||||||
|
readMore = false
|
||||||
|
}
|
||||||
|
|
||||||
|
output |= uint32(b) << shift
|
||||||
|
shift += 7
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WritePackedUInt32(v uint32) {
|
||||||
|
writeMore := true
|
||||||
|
for writeMore {
|
||||||
|
b := byte(v & 0xff)
|
||||||
|
if v >= 0x80 {
|
||||||
|
b |= 0x80
|
||||||
|
}
|
||||||
|
packet.Write(b)
|
||||||
|
v >>= 7
|
||||||
|
writeMore = v > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadString() string {
|
||||||
|
l := int(packet.ReadPackedUInt32())
|
||||||
|
return string(packet.ReadBytes(l))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteString(v string) {
|
||||||
|
l := len(v)
|
||||||
|
packet.WritePackedUInt32(uint32(l))
|
||||||
|
packet.WriteBytes([]byte(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadHazel() *Hazel {
|
||||||
|
return NewHazel(packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteHazel(hazel *Hazel) {
|
||||||
|
hazel.WriteToPacket(packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadIP() net.IP {
|
||||||
|
b := packet.ReadBytes(4)
|
||||||
|
return net.IPv4(b[0], b[1], b[2], b[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteIP(v net.IP) {
|
||||||
|
packet.Write(v[0])
|
||||||
|
packet.Write(v[1])
|
||||||
|
packet.Write(v[2])
|
||||||
|
packet.Write(v[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) ReadVector2() util.Vec2 {
|
||||||
|
x := float32(packet.ReadUInt16()) / 65535
|
||||||
|
y := float32(packet.ReadUInt16()) / 65535
|
||||||
|
|
||||||
|
return util.NewVec2(util.Lerp(-50, 50, x), util.Lerp(-50, 50, y))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packet *Packet) WriteVector2(v util.Vec2) {
|
||||||
|
x := uint16(util.LerpReverse(-50, 50, v.X) * 65535)
|
||||||
|
y := uint16(util.LerpReverse(-50, 50, v.Y) * 65535)
|
||||||
|
packet.WriteUInt16(x)
|
||||||
|
packet.WriteUInt16(y)
|
||||||
|
}
|
161
src/protocol/packethandler.go
Normal file
161
src/protocol/packethandler.go
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PacketNormal = 0x0
|
||||||
|
PacketReliable = 0x1
|
||||||
|
PacketHello = 0x8
|
||||||
|
PacketDisconnect = 0x9
|
||||||
|
PacketAcknowledgement = 0xa
|
||||||
|
PacketFragment = 0xb
|
||||||
|
PacketPing = 0xc
|
||||||
|
)
|
||||||
|
|
||||||
|
type PacketHandler struct {
|
||||||
|
conn *net.UDPConn
|
||||||
|
addr *net.UDPAddr
|
||||||
|
HandleNormalPacket func(net *PacketHandler, h []*Hazel)
|
||||||
|
HandleReliablePacket func(net *PacketHandler, id uint16, h []*Hazel)
|
||||||
|
HandleForceDisconnectPacket func(net *PacketHandler, h *Hazel)
|
||||||
|
HandleNormalDisconnectPacket func(net *PacketHandler)
|
||||||
|
HandleAcknowledgementPacket func(net *PacketHandler, nonce uint16, missing byte)
|
||||||
|
HandlePingPacket func(net *PacketHandler, id uint16)
|
||||||
|
currentNonce uint16
|
||||||
|
nonceMutex sync.Mutex
|
||||||
|
currentSequence uint16
|
||||||
|
sequenceMutex sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPacketHandler(conn *net.UDPConn, addr *net.UDPAddr) *PacketHandler {
|
||||||
|
return &PacketHandler{conn: conn, addr: addr, currentNonce: 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) GetNonce() uint16 {
|
||||||
|
ph.nonceMutex.Lock()
|
||||||
|
a := ph.currentNonce
|
||||||
|
ph.currentNonce++
|
||||||
|
ph.nonceMutex.Unlock()
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) GetSequence() uint16 {
|
||||||
|
ph.sequenceMutex.Lock()
|
||||||
|
a := ph.currentSequence
|
||||||
|
ph.currentSequence++
|
||||||
|
ph.sequenceMutex.Unlock()
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) ReadPacket(data []byte) {
|
||||||
|
p := NewPacket(data)
|
||||||
|
b := p.Read()
|
||||||
|
if b == PacketNormal {
|
||||||
|
var h []*Hazel
|
||||||
|
for p.Remaining() > 0 {
|
||||||
|
h = append(h, p.ReadHazel())
|
||||||
|
}
|
||||||
|
ph.HandleNormalPacket(ph, h)
|
||||||
|
} else if b == PacketReliable {
|
||||||
|
id := p.ReadUInt16BigEndian()
|
||||||
|
var h []*Hazel
|
||||||
|
for p.Remaining() > 0 {
|
||||||
|
h = append(h, p.ReadHazel())
|
||||||
|
}
|
||||||
|
if len(h) > 0 {
|
||||||
|
ph.HandleReliablePacket(ph, id, h)
|
||||||
|
}
|
||||||
|
} else if b == PacketHello {
|
||||||
|
// Client doesn't need to read this
|
||||||
|
} else if b == PacketDisconnect {
|
||||||
|
isForced := p.ReadBool()
|
||||||
|
if isForced {
|
||||||
|
ph.HandleForceDisconnectPacket(ph, p.ReadHazel())
|
||||||
|
} else {
|
||||||
|
ph.HandleNormalDisconnectPacket(ph)
|
||||||
|
}
|
||||||
|
} else if b == PacketAcknowledgement {
|
||||||
|
nonce := p.ReadUInt16BigEndian()
|
||||||
|
missing := p.Read()
|
||||||
|
ph.HandleAcknowledgementPacket(ph, nonce, missing)
|
||||||
|
} else if b == PacketFragment {
|
||||||
|
// Currently not used
|
||||||
|
} else if b == PacketPing {
|
||||||
|
id := p.ReadUInt16BigEndian()
|
||||||
|
ph.HandlePingPacket(ph, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) NewPacketFromType(packetType byte) *Packet {
|
||||||
|
return NewPacket([]byte{packetType})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) SendPacket(packet *Packet) {
|
||||||
|
_, err := ph.conn.Write(packet.data)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to send packet to server %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) SendNormalPacket(h []*Hazel) {
|
||||||
|
p := ph.NewPacketFromType(0x00)
|
||||||
|
for i := 0; i < len(h); i++ {
|
||||||
|
p.WriteHazel(h[i])
|
||||||
|
}
|
||||||
|
ph.SendPacket(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) SendReliablePacket(nonce uint16, h []*Hazel) {
|
||||||
|
p := ph.NewPacketFromType(0x01)
|
||||||
|
p.WriteUInt16BigEndian(nonce)
|
||||||
|
for i := 0; i < len(h); i++ {
|
||||||
|
p.WriteHazel(h[i])
|
||||||
|
}
|
||||||
|
ph.SendPacket(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) SendHelloPacket(nonce uint16, hazelVersion byte, clientVersion int32, username string, authNonce uint32, keyword uint32, quickChatMode byte) {
|
||||||
|
p := ph.NewPacketFromType(0x08)
|
||||||
|
p.WriteUInt16BigEndian(nonce)
|
||||||
|
p.Write(hazelVersion)
|
||||||
|
p.WriteInt32(clientVersion)
|
||||||
|
p.WriteString(username)
|
||||||
|
p.WriteUInt32(authNonce)
|
||||||
|
p.WriteUInt32(keyword)
|
||||||
|
p.Write(quickChatMode)
|
||||||
|
ph.SendPacket(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) SendForceDisconnectPacket(h *Hazel) {
|
||||||
|
p := ph.NewPacketFromType(0x09)
|
||||||
|
p.Write(0x01)
|
||||||
|
p.WriteHazel(h)
|
||||||
|
ph.SendPacket(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) SendNormalDisconnectPacket() {
|
||||||
|
p := ph.NewPacketFromType(0x09)
|
||||||
|
p.Write(0x00)
|
||||||
|
ph.SendPacket(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) SendAcknowledgementPacket(nonce uint16, missing byte) {
|
||||||
|
p := ph.NewPacketFromType(0x0a)
|
||||||
|
p.WriteUInt16BigEndian(nonce)
|
||||||
|
p.Write(missing)
|
||||||
|
ph.SendPacket(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) SendPingPacket(id uint16) {
|
||||||
|
p := ph.NewPacketFromType(0x0c)
|
||||||
|
p.WriteUInt16(id)
|
||||||
|
ph.conn.WriteToUDP(p.data, ph.addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *PacketHandler) Close() {
|
||||||
|
ph.conn.Close()
|
||||||
|
}
|
53
src/protocol/playerdata.go
Normal file
53
src/protocol/playerdata.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
type PlayerData struct {
|
||||||
|
PlayerID byte
|
||||||
|
Name string
|
||||||
|
ColorID uint32
|
||||||
|
HatID uint32
|
||||||
|
PetID uint32
|
||||||
|
SkinID uint32
|
||||||
|
Flags byte
|
||||||
|
Tasks []*TaskInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (player *PlayerData) Write(packet *Packet) {
|
||||||
|
packet.Write(player.PlayerID)
|
||||||
|
packet.WriteString(player.Name)
|
||||||
|
packet.WritePackedUInt32(player.ColorID)
|
||||||
|
packet.WritePackedUInt32(player.HatID)
|
||||||
|
packet.WritePackedUInt32(player.PetID)
|
||||||
|
packet.WritePackedUInt32(player.SkinID)
|
||||||
|
packet.Write(player.Flags)
|
||||||
|
packet.Write(byte(len(player.Tasks)))
|
||||||
|
for i := 0; i < len(player.Tasks); i++ {
|
||||||
|
player.Tasks[i].Write(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (player *PlayerData) Read(packet *Packet) {
|
||||||
|
player.PlayerID = packet.Read()
|
||||||
|
player.Name = packet.ReadString()
|
||||||
|
player.ColorID = packet.ReadPackedUInt32()
|
||||||
|
player.HatID = packet.ReadPackedUInt32()
|
||||||
|
player.PetID = packet.ReadPackedUInt32()
|
||||||
|
player.SkinID = packet.ReadPackedUInt32()
|
||||||
|
player.Flags = packet.Read()
|
||||||
|
player.Tasks = make([]*TaskInfo, packet.Read())
|
||||||
|
for i := 0; i < len(player.Tasks); i++ {
|
||||||
|
player.Tasks[i].Read(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type TaskInfo struct {
|
||||||
|
TaskID uint32
|
||||||
|
IsCompleted bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (task *TaskInfo) Write(packet *Packet) {
|
||||||
|
packet.WritePackedUInt32(task.TaskID)
|
||||||
|
packet.WriteBool(task.IsCompleted)
|
||||||
|
}
|
||||||
|
func (task *TaskInfo) Read(packet *Packet) {
|
||||||
|
task.TaskID = packet.ReadPackedUInt32()
|
||||||
|
task.IsCompleted = packet.ReadBool()
|
||||||
|
}
|
3
src/states/go.mod
Normal file
3
src/states/go.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module codehub.onpointcoding.net/sean/go-susapp/states
|
||||||
|
|
||||||
|
go 1.17
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user