add custom items, use proxy code for everything
This commit is contained in:
parent
e84b3ea2fe
commit
ea6dea7953
|
@ -32,6 +32,8 @@ debug_mode:
|
|||
other: "Debug-Modus"
|
||||
refreshed_token:
|
||||
other: Token wurde aktualisiert
|
||||
done:
|
||||
other: Fertig
|
||||
|
||||
starting_dns:
|
||||
other: "Starten des DNS auf {{.Ip}}:53"
|
||||
|
|
|
@ -31,7 +31,9 @@ preload_packs:
|
|||
debug_mode:
|
||||
other: "debug mode"
|
||||
refreshed_token:
|
||||
other: refreshed token
|
||||
other: "refreshed token"
|
||||
done:
|
||||
other: "done"
|
||||
|
||||
starting_dns:
|
||||
other: "Starting dns at {{.Ip}}:53"
|
||||
|
|
|
@ -30,6 +30,10 @@ preload_packs:
|
|||
other: "pwewoad wewesouwcepacks for pwoxy"
|
||||
debug_mode:
|
||||
other: "debug mode"
|
||||
refreshed_token:
|
||||
other: "refweshed token"
|
||||
done:
|
||||
other: done
|
||||
|
||||
starting_dns:
|
||||
other: "Stawting dns at {{.Ip}}:53"
|
||||
|
|
|
@ -276,36 +276,29 @@ func (c *SkinCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}
|
|||
return 1
|
||||
}
|
||||
|
||||
serverConn, err := utils.ConnectServer(ctx, address, nil, false, nil)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return 1
|
||||
}
|
||||
defer serverConn.Close()
|
||||
|
||||
out_path := fmt.Sprintf("skins/%s", hostname)
|
||||
|
||||
if err := serverConn.DoSpawnContext(ctx); err != nil {
|
||||
p := utils.NewProxy()
|
||||
p.WithClient = false
|
||||
p.ConnectCB = func(proxy *utils.ProxyContext) {
|
||||
logrus.Info(locale.Loc("connected", nil))
|
||||
logrus.Info(locale.Loc("ctrl_c_to_exit", nil))
|
||||
|
||||
os.MkdirAll(out_path, 0o755)
|
||||
}
|
||||
|
||||
p.PacketCB = func(pk packet.Packet, proxy *utils.ProxyContext, toServer bool) (packet.Packet, error) {
|
||||
if !toServer {
|
||||
process_packet_skins(nil, out_path, pk, c.filter, false)
|
||||
}
|
||||
return pk, nil
|
||||
}
|
||||
|
||||
err = p.Run(ctx, address)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return 1
|
||||
}
|
||||
|
||||
logrus.Info(locale.Loc("connected", nil))
|
||||
logrus.Info(locale.Loc("ctrl_c_to_exit", nil))
|
||||
|
||||
os.MkdirAll(out_path, 0o755)
|
||||
|
||||
for {
|
||||
pk, err := serverConn.ReadPacket()
|
||||
if err != nil {
|
||||
return 1
|
||||
}
|
||||
process_packet_skins(nil, out_path, pk, c.filter, false)
|
||||
if ctx.Err() != nil {
|
||||
serverConn.Close()
|
||||
break
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
@ -158,6 +158,7 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{
|
|||
w.saveImage = c.saveImage
|
||||
w.experimentInventory = c.experimentInventory
|
||||
w.ctx = ctx
|
||||
w.bp = behaviourpack.New(w.ServerName)
|
||||
|
||||
proxy := utils.NewProxy()
|
||||
proxy.AlwaysGetPacks = true
|
||||
|
@ -442,7 +443,7 @@ func (w *WorldState) SaveAndReset() {
|
|||
ld.Generator = 2
|
||||
}
|
||||
|
||||
if w.bp != nil {
|
||||
if w.bp.HasContent() {
|
||||
if ld.Experiments == nil {
|
||||
ld.Experiments = map[string]any{}
|
||||
}
|
||||
|
@ -489,7 +490,7 @@ func (w *WorldState) SaveAndReset() {
|
|||
add_packs_json("world_resource_packs.json", rdeps)
|
||||
}
|
||||
|
||||
if w.bp != nil {
|
||||
if w.bp.HasContent() {
|
||||
name := strings.ReplaceAll(w.ServerName, "/", "-") + "_blocks"
|
||||
pack_folder := path.Join(folder, "behavior_packs", name)
|
||||
os.MkdirAll(pack_folder, 0o755)
|
||||
|
@ -519,7 +520,7 @@ func (w *WorldState) SaveAndReset() {
|
|||
fmt.Println(err)
|
||||
}
|
||||
logrus.Info(locale.Loc("saved", locale.Strmap{"Name": filename}))
|
||||
os.RemoveAll(folder)
|
||||
// os.RemoveAll(folder)
|
||||
w.Reset()
|
||||
}
|
||||
|
||||
|
@ -529,6 +530,12 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext) {
|
|||
|
||||
world.InsertCustomItems(gd.Items)
|
||||
|
||||
for _, ie := range gd.Items {
|
||||
if ie.ComponentBased {
|
||||
w.bp.AddItem(ie)
|
||||
}
|
||||
}
|
||||
|
||||
map_item_id, _ := world.ItemRidByName("minecraft:filled_map")
|
||||
MAP_ITEM_PACKET.Content[0].Stack.ItemType.NetworkID = map_item_id
|
||||
if gd.ServerAuthoritativeInventory {
|
||||
|
@ -537,12 +544,9 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext) {
|
|||
|
||||
if len(gd.CustomBlocks) > 0 {
|
||||
logrus.Info(locale.Loc("using_customblocks", nil))
|
||||
|
||||
w.bp = behaviourpack.New(w.ServerName + " Custom Blocks")
|
||||
for _, be := range gd.CustomBlocks {
|
||||
w.bp.AddBlock(be)
|
||||
}
|
||||
|
||||
// telling the chunk code what custom blocks there are so it can generate offsets
|
||||
world.InsertCustomBlocks(gd.CustomBlocks)
|
||||
}
|
||||
|
@ -785,6 +789,8 @@ func (w *WorldState) ProcessPacketServer(pk packet.Packet) (packet.Packet, bool)
|
|||
delete(w.openItemContainers, byte(pk.WindowID))
|
||||
}
|
||||
}
|
||||
case *packet.ItemComponent:
|
||||
w.bp.ApplyComponentEntries(pk.Items)
|
||||
}
|
||||
return pk, true
|
||||
}
|
||||
|
|
|
@ -18,8 +18,10 @@ import (
|
|||
)
|
||||
|
||||
type BehaviourPack struct {
|
||||
Manifest *resource.Manifest
|
||||
blocks []blockBehaviour
|
||||
formatVersion string
|
||||
Manifest *resource.Manifest
|
||||
blocks []blockBehaviour
|
||||
items map[string]itemBehaviour
|
||||
}
|
||||
|
||||
type blockBehaviour struct {
|
||||
|
@ -27,6 +29,22 @@ type blockBehaviour struct {
|
|||
MinecraftBlock world.MinecraftBlock `json:"minecraft:block"`
|
||||
}
|
||||
|
||||
type itemDescription struct {
|
||||
Category string `json:"category"`
|
||||
Identifier string `json:"identifier"`
|
||||
IsExperimental bool `json:"is_experimental"`
|
||||
}
|
||||
|
||||
type minecraftItem struct {
|
||||
Description itemDescription `json:"description"`
|
||||
Components map[string]any `json:"components,omitempty"`
|
||||
}
|
||||
|
||||
type itemBehaviour struct {
|
||||
FormatVersion string `json:"format_version"`
|
||||
MinecraftItem minecraftItem `json:"minecraft:item"`
|
||||
}
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
|
@ -41,6 +59,7 @@ func rand_seeded_uuid(str string) string {
|
|||
|
||||
func New(name string) *BehaviourPack {
|
||||
return &BehaviourPack{
|
||||
formatVersion: "1.16.0",
|
||||
Manifest: &resource.Manifest{
|
||||
FormatVersion: 2,
|
||||
Header: resource.Header{
|
||||
|
@ -60,6 +79,8 @@ func New(name string) *BehaviourPack {
|
|||
Dependencies: []resource.Dependency{},
|
||||
Capabilities: []resource.Capability{},
|
||||
},
|
||||
blocks: []blockBehaviour{},
|
||||
items: make(map[string]itemBehaviour),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,17 +93,42 @@ func (bp *BehaviourPack) AddDependency(id string, ver [3]int) {
|
|||
|
||||
func (bp *BehaviourPack) AddBlock(block protocol.BlockEntry) {
|
||||
entry := blockBehaviour{
|
||||
FormatVersion: "1.16.0",
|
||||
FormatVersion: bp.formatVersion,
|
||||
MinecraftBlock: world.ParseBlock(block),
|
||||
}
|
||||
|
||||
bp.blocks = append(bp.blocks, entry)
|
||||
}
|
||||
|
||||
func (bp *BehaviourPack) AddItem(item protocol.ItemEntry) {
|
||||
entry := itemBehaviour{
|
||||
FormatVersion: bp.formatVersion,
|
||||
MinecraftItem: minecraftItem{
|
||||
Description: itemDescription{
|
||||
Identifier: item.Name,
|
||||
IsExperimental: true,
|
||||
},
|
||||
Components: make(map[string]any),
|
||||
},
|
||||
}
|
||||
bp.items[item.Name] = entry
|
||||
}
|
||||
|
||||
func (bp *BehaviourPack) ApplyComponentEntries(entries []protocol.ItemComponentEntry) {
|
||||
for _, ice := range entries {
|
||||
item, ok := bp.items[ice.Name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
item.MinecraftItem.Components = ice.Data
|
||||
}
|
||||
}
|
||||
|
||||
func (bp *BehaviourPack) CheckAddLink(pack utils.Pack) {
|
||||
z, err := zip.NewReader(pack, int64(pack.Len()))
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
_, err = z.Open("blocks.json")
|
||||
if err != nil {
|
||||
|
@ -92,25 +138,54 @@ func (bp *BehaviourPack) CheckAddLink(pack utils.Pack) {
|
|||
bp.AddDependency(h.UUID, h.Version)
|
||||
}
|
||||
|
||||
func (bp *BehaviourPack) HasContent() bool {
|
||||
return len(bp.blocks) > 0 || len(bp.items) > 0
|
||||
}
|
||||
|
||||
func (bp *BehaviourPack) Save(fpath string) error {
|
||||
{ // write manifest
|
||||
w, err := os.Create(path.Join(fpath, "manifest.json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
check(json.NewEncoder(w).Encode(bp.Manifest))
|
||||
e := json.NewEncoder(w)
|
||||
e.SetIndent("", "\t")
|
||||
check(e.Encode(bp.Manifest))
|
||||
}
|
||||
{ // blocks
|
||||
block_dir := path.Join(fpath, "blocks")
|
||||
os.Mkdir(block_dir, 0o755)
|
||||
if len(bp.blocks) > 0 { // blocks
|
||||
blocks_dir := path.Join(fpath, "blocks")
|
||||
os.Mkdir(blocks_dir, 0o755)
|
||||
for _, be := range bp.blocks {
|
||||
ns := strings.Split(be.MinecraftBlock.Description.Identifier, ":")
|
||||
name := ns[len(ns)-1]
|
||||
ns_name := strings.Split(be.MinecraftBlock.Description.Identifier, ":")
|
||||
ns := ns_name[0]
|
||||
name := ns_name[len(ns_name)-1]
|
||||
block_dir := path.Join(blocks_dir, ns)
|
||||
os.Mkdir(block_dir, 0o755)
|
||||
w, err := os.Create(path.Join(block_dir, name+".json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
check(json.NewEncoder(w).Encode(be))
|
||||
e := json.NewEncoder(w)
|
||||
e.SetIndent("", "\t")
|
||||
check(e.Encode(be))
|
||||
}
|
||||
}
|
||||
if len(bp.items) > 0 { // items
|
||||
items_dir := path.Join(fpath, "items")
|
||||
os.Mkdir(items_dir, 0o755)
|
||||
for _, ib := range bp.items {
|
||||
ns_name := strings.Split(ib.MinecraftItem.Description.Identifier, ":")
|
||||
ns := ns_name[0]
|
||||
name := ns_name[len(ns_name)-1]
|
||||
item_dir := path.Join(items_dir, ns)
|
||||
os.Mkdir(item_dir, 0o755)
|
||||
w, err := os.Create(path.Join(item_dir, name+".json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e := json.NewEncoder(w)
|
||||
e.SetIndent("", "\t")
|
||||
check(e.Encode(ib))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
127
utils/proxy.go
127
utils/proxy.go
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/bedrock-tool/bedrocktool/locale"
|
||||
"github.com/sandertv/gophertunnel/minecraft"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/login"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
"github.com/sandertv/gophertunnel/minecraft/resource"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -40,6 +41,7 @@ type ProxyContext struct {
|
|||
Listener *minecraft.Listener
|
||||
commands map[string]IngameCommand
|
||||
AlwaysGetPacks bool
|
||||
WithClient bool
|
||||
|
||||
// called for every packet
|
||||
PacketFunc PacketFunc
|
||||
|
@ -105,14 +107,14 @@ func (p *ProxyContext) CommandHandlerPacketCB(pk packet.Packet, proxy *ProxyCont
|
|||
return pk, nil
|
||||
}
|
||||
|
||||
func proxyLoop(ctx context.Context, proxy *ProxyContext, toServer bool, packetCBs []PacketCallback) error {
|
||||
func (p *ProxyContext) proxyLoop(ctx context.Context, toServer bool, packetCBs []PacketCallback) error {
|
||||
var c1, c2 *minecraft.Conn
|
||||
if toServer {
|
||||
c1 = proxy.Client
|
||||
c2 = proxy.Server
|
||||
c1 = p.Client
|
||||
c2 = p.Server
|
||||
} else {
|
||||
c1 = proxy.Server
|
||||
c2 = proxy.Client
|
||||
c1 = p.Server
|
||||
c2 = p.Client
|
||||
}
|
||||
|
||||
for {
|
||||
|
@ -126,13 +128,13 @@ func proxyLoop(ctx context.Context, proxy *ProxyContext, toServer bool, packetCB
|
|||
}
|
||||
|
||||
for _, packetCB := range packetCBs {
|
||||
pk, err = packetCB(pk, proxy, toServer)
|
||||
pk, err = packetCB(pk, p, toServer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if pk != nil {
|
||||
if pk != nil && c2 != nil {
|
||||
if err := c2.WritePacket(pk); err != nil {
|
||||
if disconnect, ok := errors.Unwrap(err).(minecraft.DisconnectError); ok {
|
||||
G_disconnect_reason = disconnect.Error()
|
||||
|
@ -145,7 +147,8 @@ func proxyLoop(ctx context.Context, proxy *ProxyContext, toServer bool, packetCB
|
|||
|
||||
func NewProxy() *ProxyContext {
|
||||
return &ProxyContext{
|
||||
commands: make(map[string]IngameCommand),
|
||||
commands: make(map[string]IngameCommand),
|
||||
WithClient: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,50 +163,54 @@ func (p *ProxyContext) Run(ctx context.Context, server_address string) (err erro
|
|||
}
|
||||
|
||||
GetTokenSource() // ask for login before listening
|
||||
var packs []*resource.Pack
|
||||
if G_preload_packs {
|
||||
logrus.Info(locale.Loc("preloading_packs", nil))
|
||||
var serverConn *minecraft.Conn
|
||||
serverConn, err = ConnectServer(ctx, server_address, nil, true, nil)
|
||||
|
||||
var cdp *login.ClientData = nil
|
||||
if p.WithClient {
|
||||
var packs []*resource.Pack
|
||||
if G_preload_packs {
|
||||
logrus.Info(locale.Loc("preloading_packs", nil))
|
||||
var serverConn *minecraft.Conn
|
||||
serverConn, err = connectServer(ctx, server_address, nil, true, nil)
|
||||
if err != nil {
|
||||
err = fmt.Errorf(locale.Loc("failed_to_connect", locale.Strmap{"Address": server_address, "Err": err}))
|
||||
return
|
||||
}
|
||||
serverConn.Close()
|
||||
packs = serverConn.ResourcePacks()
|
||||
logrus.Infof(locale.Locm("pack_count_loaded", locale.Strmap{"Count": len(packs)}, len(packs)))
|
||||
}
|
||||
|
||||
_status := minecraft.NewStatusProvider("Server")
|
||||
p.Listener, err = minecraft.ListenConfig{
|
||||
StatusProvider: _status,
|
||||
ResourcePacks: packs,
|
||||
AcceptedProtocols: []minecraft.Protocol{
|
||||
dummyProto{id: 544, ver: "1.19.20"},
|
||||
},
|
||||
}.Listen("raknet", ":19132")
|
||||
if err != nil {
|
||||
err = fmt.Errorf(locale.Loc("failed_to_connect", locale.Strmap{"Address": server_address, "Err": err}))
|
||||
return
|
||||
}
|
||||
serverConn.Close()
|
||||
packs = serverConn.ResourcePacks()
|
||||
logrus.Infof(locale.Locm("pack_count_loaded", locale.Strmap{"Count": len(packs)}, len(packs)))
|
||||
defer p.Listener.Close()
|
||||
|
||||
logrus.Infof(locale.Loc("listening_on", locale.Strmap{"Address": p.Listener.Addr()}))
|
||||
logrus.Infof(locale.Loc("help_connect", nil))
|
||||
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
p.Listener.Close()
|
||||
}()
|
||||
|
||||
var c net.Conn
|
||||
c, err = p.Listener.Accept()
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
p.Client = c.(*minecraft.Conn)
|
||||
cd := p.Client.ClientData()
|
||||
cdp = &cd
|
||||
}
|
||||
|
||||
_status := minecraft.NewStatusProvider("Server")
|
||||
p.Listener, err = minecraft.ListenConfig{
|
||||
StatusProvider: _status,
|
||||
ResourcePacks: packs,
|
||||
AcceptedProtocols: []minecraft.Protocol{
|
||||
dummyProto{id: 544, ver: "1.19.20"},
|
||||
},
|
||||
}.Listen("raknet", ":19132")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer p.Listener.Close()
|
||||
|
||||
logrus.Infof(locale.Loc("listening_on", locale.Strmap{"Address": p.Listener.Addr()}))
|
||||
logrus.Infof(locale.Loc("help_connect", nil))
|
||||
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
p.Listener.Close()
|
||||
}()
|
||||
|
||||
var c net.Conn
|
||||
c, err = p.Listener.Accept()
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
p.Client = c.(*minecraft.Conn)
|
||||
|
||||
cd := p.Client.ClientData()
|
||||
p.Server, err = ConnectServer(ctx, server_address, &cd, p.AlwaysGetPacks, p.PacketFunc)
|
||||
p.Server, err = connectServer(ctx, server_address, cdp, p.AlwaysGetPacks, p.PacketFunc)
|
||||
if err != nil {
|
||||
err = fmt.Errorf(locale.Loc("failed_to_connect", locale.Strmap{"Address": server_address, "Err": err}))
|
||||
return
|
||||
|
@ -215,7 +222,9 @@ func (p *ProxyContext) Run(ctx context.Context, server_address string) (err erro
|
|||
}
|
||||
|
||||
defer p.Server.Close()
|
||||
defer p.Listener.Disconnect(p.Client, G_disconnect_reason)
|
||||
if p.Listener != nil {
|
||||
defer p.Listener.Disconnect(p.Client, G_disconnect_reason)
|
||||
}
|
||||
|
||||
if p.ConnectCB != nil {
|
||||
p.ConnectCB(p)
|
||||
|
@ -233,21 +242,23 @@ func (p *ProxyContext) Run(ctx context.Context, server_address string) (err erro
|
|||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := proxyLoop(ctx, p, false, cbs); err != nil {
|
||||
if err := p.proxyLoop(ctx, false, cbs); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
// client to server
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := proxyLoop(ctx, p, true, cbs); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
if p.Client != nil {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := p.proxyLoop(ctx, true, cbs); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return err
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"context"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/sandertv/gophertunnel/minecraft"
|
||||
|
@ -85,7 +84,7 @@ func create_replay_connection(ctx context.Context, filename string, onConnect Co
|
|||
b := protocol.NewWriter(f, 0)
|
||||
pk.Marshal(b)
|
||||
|
||||
PacketLogger(packet.Header{PacketID: pk.ID()}, f.Bytes(), &net.UDPAddr{}, &net.UDPAddr{})
|
||||
// PacketLogger(packet.Header{PacketID: pk.ID()}, f.Bytes(), &net.UDPAddr{}, &net.UDPAddr{})
|
||||
|
||||
if game_started {
|
||||
if packetCB != nil {
|
||||
|
|
Binary file not shown.
|
@ -8,6 +8,7 @@ import (
|
|||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/bedrock-tool/bedrocktool/locale"
|
||||
"github.com/google/uuid"
|
||||
|
@ -45,7 +46,7 @@ func CleanupName(name string) string {
|
|||
|
||||
// connections
|
||||
|
||||
func ConnectServer(ctx context.Context, address string, ClientData *login.ClientData, want_packs bool, packetFunc PacketFunc) (serverConn *minecraft.Conn, err error) {
|
||||
func connectServer(ctx context.Context, address string, ClientData *login.ClientData, want_packs bool, packetFunc PacketFunc) (serverConn *minecraft.Conn, err error) {
|
||||
packet_func := func(header packet.Header, payload []byte, src, dst net.Addr) {
|
||||
if G_debug {
|
||||
PacketLogger(header, payload, src, dst)
|
||||
|
@ -79,15 +80,22 @@ func ConnectServer(ctx context.Context, address string, ClientData *login.Client
|
|||
}
|
||||
|
||||
func spawn_conn(ctx context.Context, clientConn *minecraft.Conn, serverConn *minecraft.Conn) error {
|
||||
wg := sync.WaitGroup{}
|
||||
errs := make(chan error, 2)
|
||||
if clientConn != nil {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
errs <- clientConn.StartGame(serverConn.GameData())
|
||||
}()
|
||||
}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
errs <- clientConn.StartGame(serverConn.GameData())
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
errs <- serverConn.DoSpawn()
|
||||
}()
|
||||
|
||||
// wait for both to finish
|
||||
wg.Wait()
|
||||
for i := 0; i < 2; i++ {
|
||||
select {
|
||||
case err := <-errs:
|
||||
|
@ -96,6 +104,7 @@ func spawn_conn(ctx context.Context, clientConn *minecraft.Conn, serverConn *min
|
|||
}
|
||||
case <-ctx.Done():
|
||||
return errors.New(locale.Loc("connection_cancelled", nil))
|
||||
default:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
Loading…
Reference in New Issue