add custom items, use proxy code for everything

This commit is contained in:
olebeck 2023-01-29 01:44:32 +00:00
parent e84b3ea2fe
commit ea6dea7953
10 changed files with 208 additions and 107 deletions

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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