From ea6dea79531c047c8ccc05769e92583dfb246d82 Mon Sep 17 00:00:00 2001 From: olebeck <31539311+olebeck@users.noreply.github.com> Date: Sun, 29 Jan 2023 01:44:32 +0000 Subject: [PATCH] add custom items, use proxy code for everything --- locale/de.yaml | 2 + locale/en.yaml | 4 +- locale/owo.yaml | 4 ++ subcommands/skins/skins.go | 43 ++++++------- subcommands/world/world.go | 18 ++++-- utils/behaviourpack/bp.go | 95 ++++++++++++++++++++++++--- utils/proxy.go | 127 ++++++++++++++++++++----------------- utils/replay.go | 3 +- utils/resourcepack-ace.go | Bin 6218 -> 6449 bytes utils/utils.go | 19 ++++-- 10 files changed, 208 insertions(+), 107 deletions(-) diff --git a/locale/de.yaml b/locale/de.yaml index 3cd9edc..1922116 100644 --- a/locale/de.yaml +++ b/locale/de.yaml @@ -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" diff --git a/locale/en.yaml b/locale/en.yaml index 0a7dec3..59dab53 100644 --- a/locale/en.yaml +++ b/locale/en.yaml @@ -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" diff --git a/locale/owo.yaml b/locale/owo.yaml index 04881e1..6420bbd 100644 --- a/locale/owo.yaml +++ b/locale/owo.yaml @@ -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" diff --git a/subcommands/skins/skins.go b/subcommands/skins/skins.go index aaf5ef0..5bf20c8 100644 --- a/subcommands/skins/skins.go +++ b/subcommands/skins/skins.go @@ -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 } diff --git a/subcommands/world/world.go b/subcommands/world/world.go index f43529f..7df846e 100644 --- a/subcommands/world/world.go +++ b/subcommands/world/world.go @@ -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 } diff --git a/utils/behaviourpack/bp.go b/utils/behaviourpack/bp.go index 00f1eea..7ddc7cf 100644 --- a/utils/behaviourpack/bp.go +++ b/utils/behaviourpack/bp.go @@ -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 diff --git a/utils/proxy.go b/utils/proxy.go index 29501b4..3a7a855 100644 --- a/utils/proxy.go +++ b/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 diff --git a/utils/replay.go b/utils/replay.go index dece900..8619064 100644 --- a/utils/replay.go +++ b/utils/replay.go @@ -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 { diff --git a/utils/resourcepack-ace.go b/utils/resourcepack-ace.go index 7030c8ef0f3550db1f5fdacb4c9c5035a8aba52a..790e6efd89c4c9833b5af2225c1fa7b9052fdbd5 100644 GIT binary patch literal 6449 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 diff --git a/utils/utils.go b/utils/utils.go index 3a6e30d..c70b234 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -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