diff --git a/locale/de.yaml b/locale/de.yaml new file mode 100644 index 0000000..13be68d --- /dev/null +++ b/locale/de.yaml @@ -0,0 +1,188 @@ +bedrocktool_version: + other: "Bedrocktool Version {{.Version}}" +available_commands: + other: "Verfügbare Befehle:" +use_to_run_command: + other: "Verwenden Sie 'bedrocktool ', um einen Befehl auszuführen" +input_command: + other: "Eingabeaufforderung: " +fatal_error: + other: "Schwerer Fehler aufgetreten." +report_issue: + other: | + Wenn Sie diesen Fehler melden möchten, öffnen Sie bitte ein Problem unter + https://github.com/bedrock-tool/bedrocktool/issues + Und fügen Sie die Fehlerinformationen hinzu, beschreiben Sie, was Sie getan haben, um diesen Fehler zu erhalten. + Vielen Dank! +enter_to_exit: + other: "Drücken Sie die Eingabetaste, um das Programm zu beenden." +should_login_xbox: + other: "ob es sich bei Xbox anmelden soll" +enable_dns: + other: "DNS-Server für Konsolen aktivieren" +preload_packs: + other: "Vorladen von Ressourcenpacks für den Proxy" +debug_mode: + other: "Debug-Modus" + +starting_dns: + other: "Starten des DNS auf {{.Ip}}:53" +failed_to_start_dns: + other: "Fehler beim Starten des DNS-Servers: {{.Err}}" +suggest_bedrockconnect: + other: "Sie müssen möglicherweise Bedrockconnect verwenden" + +invalid_server: + other: "Ungültige Serveradresse" +enter_server: + other: "Server eingeben: " +disconnect: + other: "Verbindung trennen {{.Pk}}" +preloading_packs: + other: "Ressourcenpacks werden vorgeladen" +failed_to_connect: + other: "Verbindung zu {{.Address}} fehlgeschlagen: {{.Err}}" +listening_on: + other: "Hört auf {{.Address}}" +connecting: + other: "Verbindung wird hergestellt mit {{.Address}}" +connected: + other: "Verbunden mit dem Server." +connection_cancelled: + other: "Verbindung abgebrochen" +failed_start_game: + other: "Das Spiel konnte nicht gestartet werden: {{.Err}}" +help_connect: + other: "Starten Sie Minecraft und verbinden Sie sich mit der lokalen IP-Adresse dieses Computers, um fortzufahren" +failed_to_spawn: + other: "Spawn fehlgeschlagen" +not_supported_anymore: + other: "wird nicht mehr unterstützt" +remote_address: + other: "entfernte Serveradresse" +ctrl_c_to_exit: + other: "Drücken Sie Strg+C, um das Programm zu beenden" +server_address_help: + other: | + akzeptierte Serveradressformate: + 123.234.123.234 + 123.234.123.234:19132 + realm: + realm:: + +realm_list_line: + other: "Name: {{.Name}}\tid: {{.Id}}" + +failed_to_open_output: + other: "Fehler beim Öffnen der Ausgabe" +adding_world: + other: "{{.World}} wird hinzugefügt" +not_found: + other: "{{.World}} nicht gefunden" +need_to_specify_multiple_worlds: + other: "Sie müssen mehr als 1 Welt angeben, um diese zu vereinen" + +update_available: + other: "Update verfügbar: {{.Version}} Verwenden Sie den Befehl 'update', um es zu installieren." +no_update: + other: "Kein Update verfügbar." +updating: + other: "Aktualisiere auf {{.Version}}" +updated: + other: "Aktualisiert!" + +worldname_set: + other: "worldName ist jetzt {{.Name}}" +void_generator_true: + other: "Verwende Void Generator" +void_generator_false: + other: "Verwende keinen Void Generator" +subchunk_before_chunk: + other: "Der Server hat den Chunk vor dem Subchunk nicht gesendet!" +zoom_level: + other: "Zoom: {{.Level}}" +not_saving_empty: + other: "Speichern wird übersprungen, da die Welt keine Chunks enthält." +saving_world: + one: "Speichere Welt {{.Name}} mit {{.Count}} Chunk" + other: "Speichere Welt {{.Name}} mit {{.Count}} Chunks" +unknown_gamerule: + other: "unbekannte Gamerule: {{.Name}}" +adding_pack: + other: "Füge Resourcepack {{.Name}} hinzu" +using_customblocks: + other: "Verwende Custom Blocks" +guessing_version: + other: "konnte die Spieleversion nicht bestimmen, gehe davon aus, dass es > 1.18 ist" +use_setname: + other: "verwende /setname \num den Weltnamen zu setzen" +using_under_118: + other: "verwende legacy (< 1.18)" +setname_desc: + other: "setze benutzerdefinierten Namen für diese Welt" +void_desc: + other: "schalte ein/aus ob der Void Generator verwendet werden soll" +popup_chunk_count: + one: "{{.Count}} Chunk geladen\nName: {{.Name}}" + other: "{{.Count}} Chunks geladen\nName: {{.Name}}" +warn_window_closed_not_open: + other: "Schloss Fenster, das nicht geöffnet war" +saved_block_inv: + other: "Blockinventar gespeichert" +save_packs_with_world: + other: "speichere Resourcepacks mit der Welt" +enable_void: + other: "speichere mit Void Generator" +save_image: + other: "speichert am Ende ein PNG der Karte" +test_block_inv: + other: "aktiviere experimentelles Speichern des Blockinventars" +saved: + other: "Gespeichert: {{.Name}}" + +only_with_geometry: + other: "speichere nur Skins mit Geometrie" +name_prefix: + other: "speichere nur Spieler, die mit diesem beginnen" +failed_write: + other: "Fehler beim Schreiben von {{.Part}} {{.Path}}: {{.Err}}" +packet_filter: + other: "zu ignorierende Pakete" + +save_encrypted: + other: "speichere verschlüsselte Resourcepacks" +only_keys: + other: "speichere nur Schlüssel, entschlüssel das Pack nicht" +decrypting_packs: + other: "Entschlüsselung der Resource Packs" +no_resourcepacks: + other: "Kein Resourcepack gesendet" +writing_keys: + other: "Schreibe Schlüssel nach {{.Path}}" +warn_key_exists: + other: "Schlüssel {{.Id}} existiert bereits" +compare_key: + other: "uuid: {{.Id}}, Schlüssel in der DB: {{.Prev}} != neuer Schlüssel {{.Now}}" +decrypting: + other: "Entschlüsselung..." + +list_realms_synopsis: + other: "gibt alle Realm aus, auf die Sie Zugriff haben" +capture_synopsis: + other: "protokolliert Pakete in eine pcap-Datei" +chat_log_synopsis: + other: "protokolliert Chat in eine Datei" +debug_proxy_synopsis: + other: "detaillierte Debug-Pakete" +merge_synopsis: + other: "führt 2 oder mehr Welten zusammen" +update_synopsis: + other: "aktualisiert sich selbst auf die neueste Version" +skins_proxy_synopsis: + other: "lädt Skins von Spielern auf einem Server über einen Proxy herunter" +skins_synopsis: + other: "lädt Skins von Spielern auf einem Server herunter" +world_synopsis: + other: "lädt eine Welt von einem Server herunter" +pack_synopsis: + other: "lädt Resourcepacks von einem Server herunter" diff --git a/locale/en.yaml b/locale/en.yaml index c229dae..20e27cd 100644 --- a/locale/en.yaml +++ b/locale/en.yaml @@ -137,6 +137,8 @@ save_image: other: "saves an png of the map at the end" test_block_inv: other: "enable experimental block inventory saving" +saved: + other: "Saved: {{.Name}}" only_with_geometry: other: "only save skins with geometry" diff --git a/locale/owo.yaml b/locale/owo.yaml index 7d77a4f..03df319 100644 --- a/locale/owo.yaml +++ b/locale/owo.yaml @@ -137,6 +137,8 @@ save_image: other: "saves an png of the map at the end" test_block_inv: other: "enable experimental bwock inventory saving" +saved: + other: "Saved: {{.Name}}" only_with_geometry: other: "only save skins with geometry" diff --git a/subcommands/world/world.go b/subcommands/world/world.go index ee72948..8eac5c6 100644 --- a/subcommands/world/world.go +++ b/subcommands/world/world.go @@ -3,6 +3,7 @@ package world import ( "bytes" "context" + "encoding/json" "flag" "fmt" "image" @@ -452,9 +453,27 @@ func (w *WorldState) SaveAndReset() { if w.bp != nil { name := w.ServerName + "_blocks" - pack_folder := path.Join(folder, "behaviour_packs", name) + pack_folder := path.Join(folder, "behavior_packs", name) os.MkdirAll(pack_folder, 0o755) w.bp.Save(pack_folder) + { // save file saying to load the behavior pack + f, err := os.Create(path.Join(folder, "world_behavior_packs.json")) + if err != nil { + logrus.Error(err) + } else { + defer f.Close() + type dep struct { + PackId string `json:"pack_id"` + Version [3]int `json:"version"` + } + if err := json.NewEncoder(f).Encode([]dep{{ + PackId: w.bp.Manifest.Header.UUID, + Version: w.bp.Manifest.Header.Version, + }}); err != nil { + logrus.Error(err) + } + } + } } if w.saveImage { @@ -469,7 +488,7 @@ func (w *WorldState) SaveAndReset() { if err := utils.ZipFolder(filename, folder); err != nil { fmt.Println(err) } - logrus.Infof("Saved: %s", filename) + logrus.Info(locale.Loc("saved", locale.Strmap{"Name": filename})) os.RemoveAll(folder) w.Reset() } @@ -485,6 +504,7 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext) { 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) } diff --git a/utils/behaviourpack/bp.go b/utils/behaviourpack/bp.go index ddc8b55..36f619c 100644 --- a/utils/behaviourpack/bp.go +++ b/utils/behaviourpack/bp.go @@ -25,9 +25,54 @@ type description struct { RegisterToCreativeMenu bool `json:"register_to_creative_menu"` } +type menu_category struct { + Category string `json:"category"` + Group string `json:"group"` +} + +func menu_category_from_map(in map[string]any) menu_category { + return menu_category{ + Category: in["category"].(string), + Group: in["group"].(string), + } +} + +type permutation struct { + Components map[string]any `json:"components"` + Condition string `json:"condition"` +} + +func permutations_from_list(in []map[string]any) (out []permutation) { + for _, v := range in { + out = append(out, permutation{ + Components: v["components"].(map[string]any), + Condition: v["condition"].(string), + }) + } + return +} + +type property struct { + Enum []any `json:"enum"` + Name string `json:"name"` +} + +func properties_from_list(in []map[string]any) (out []property) { + for _, v := range in { + out = append(out, property{ + Enum: v["enum"].([]any), + Name: v["name"].(string), + }) + } + return +} + type minecraftBlock struct { - Description description `json:"description"` - Components map[string]interface{} `json:"components"` + Description description `json:"description"` + Components map[string]any `json:"components,omitempty"` + MenuCategory menu_category `json:"menu_category,omitempty"` + Permutations []permutation `json:"permutations,omitempty"` + Properties []property `json:"properties,omitempty"` } type blockBehaviour struct { @@ -56,7 +101,7 @@ func New(name string) *BehaviourPack { Description: "pack.description", UUID: rand_seeded_uuid(name + "_datapack"), Version: [3]int{1, 0, 0}, - MinimumGameVersion: [3]int{1, 16, 0}, + MinimumGameVersion: [3]int{1, 19, 50}, }, Modules: []resource.Module{ { @@ -71,18 +116,71 @@ func New(name string) *BehaviourPack { } } +func (bp *BehaviourPack) AddDependency(id string, ver [3]int) { + bp.Manifest.Dependencies = append(bp.Manifest.Dependencies, resource.Dependency{ + UUID: id, + Version: ver, + }) +} + func (bp *BehaviourPack) AddBlock(block protocol.BlockEntry) { entry := blockBehaviour{ - FormatVersion: "1.12.0", + FormatVersion: "1.16.0", MinecraftBlock: minecraftBlock{ Description: description{ Identifier: block.Name, - IsExperimental: false, + IsExperimental: true, RegisterToCreativeMenu: true, }, - Components: block.Properties, }, } + + v2 := false + + if perms, ok := block.Properties["permutations"].([]map[string]any); ok { + entry.MinecraftBlock.Permutations = permutations_from_list(perms) + v2 = true + } + + if comps, ok := block.Properties["components"].(map[string]any); ok { + delete(comps, "minecraft:creative_category") + + for k, v := range comps { + if v, ok := v.(map[string]any); ok { + // fix {"value": 0.1} -> 0.1 + if v, ok := v["value"]; ok { + comps[k] = v + } + // fix {"lightLevel": 15} -> 15 + if v, ok := v["lightLevel"]; ok { + comps[k] = v + } + // fix missing * instance + if k == "minecraft:material_instances" { + if mats, ok := v["materials"].(map[string]any); ok { + if _, has_star := mats["*"]; !has_star { + mats["*"] = mats["east"] + } + } + } + } + } + entry.MinecraftBlock.Components = comps + v2 = true + } + + if menu, ok := block.Properties["menu_category"].(map[string]any); ok { + entry.MinecraftBlock.MenuCategory = menu_category_from_map(menu) + v2 = true + } + if props, ok := block.Properties["properties"].([]map[string]any); ok { + entry.MinecraftBlock.Properties = properties_from_list(props) + v2 = true + } + if !v2 { + entry.MinecraftBlock.Components = block.Properties + } + bp.blocks = append(bp.blocks, entry) } diff --git a/utils/packet_logger.go b/utils/packet_logger.go index 813ecdc..38c464c 100644 --- a/utils/packet_logger.go +++ b/utils/packet_logger.go @@ -13,7 +13,7 @@ import ( "golang.org/x/exp/slices" ) -var Pool = packet.NewPool() +var pool = packet.NewPool() var MutedPackets = []string{ "packet.UpdateBlock", @@ -47,7 +47,7 @@ var ExtraVerbose []string func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) { var pk packet.Packet - if pkFunc, ok := Pool[header.PacketID]; ok { + if pkFunc, ok := pool[header.PacketID]; ok { pk = pkFunc() } else { pk = &packet.Unknown{PacketID: header.PacketID}