39 Commits
Author SHA1 Message Date
adman 69e9857bad Merge remote-tracking branch 'gitlab/master'
Go / build (push) Successful in 1m9s
2026-08-17 18:12:52 +02:00
adman d0aec490cc remove binary test files 2026-08-17 18:08:49 +02:00
adman a01cb08672 Merge remote-tracking branch 'origin/master' 2026-08-17 18:08:08 +02:00
adman 326affe364 add version flag to packet inspector 2026-08-17 18:07:51 +02:00
OpenCode 1b2552492b remove binary testdata and fuzz corpus; restore regression tests
Go / build (push) Successful in 39s
2026-08-06 15:54:37 +02:00
OpenCode 44ec148be4 remove .gitattributes and LFS, drop large replay testdata
Go / build (push) Successful in 1m1s
2026-08-06 15:52:07 +02:00
OpenCode 78442c5c68 migrate: move module path to git.anygate.cloud/anygatecloud/strom
Go / build (push) Failing after 9s
2026-08-06 15:43:20 +02:00
OpenCode ac12f5c93b chore: sync all proto_generated versions
Go / build (push) Failing after 50s
2026-08-06 15:20:42 +02:00
OpenCode e58499ed09 fix: correct bitfield decoder using mask extraction, fix command_node
- Switch bitfield decoder from shift-based to mask-based extraction (var>>pos & mask)
  fixes non-power-of-2 bitfields like 6-bit command_node flags
- Fix MultiTypeFix to handle CaseExprTypeOnlyNumber/OnlyBool variants
- Update minecraft-data command_node bitfield order for all 1.21.8+ versions
  to LSB-first convention (matches reverse encoder/decoder)
- Implement SwitchDecoder for extraNodeData via compareTo visitor
- DeclareCommands now decodes successfully (was EOF)
- Add 6 regression tests (entity_equipment, metadata, recipes, commands)
2026-08-05 22:29:08 +02:00
OpenCode f4c2762881 fix: update 26.2 SlotDisplay mapper with 3 new types from decompiled source
- Add with_any_potion (id 2), only_with_component (id 3), dyed (id 7)
- Shift existing IDs: item 2→4, item_stack 3→5, tag 4→6,
  smithing_trim 5→8, with_remainder 6→9, composite 7→10
- RecipeBookAdd now decodes successfully (was index not found)
- Verified against decompiled client jar via SlotDisplays.bootstrap()
2026-08-05 21:19:07 +02:00
OpenCode 53d366ae53 fix: implement IDSet (registryEntryHolderSet) decoder/encoder
- Replace old broken RegistryEntryHolderSetDecoder with correct varint
  discriminator: id != 0 returns raw ID, id == 0 decodes string base
- Add RegistryEntryHolderSetEncoder using type switch (string/int32)
- Add NonErroringIndex to proto_base (zero-fallback index lookup)
- DeclareRecipes now fails with index not found (mapper) instead of to do
2026-08-05 19:53:46 +02:00
OpenCode 56ac8e154e test: add 4 decode regression tests for recently fixed packets
- entity_equipment 1.8 (nbt TAG_End fix)
- entity_equipment 26.2 (topBitSetTerminatedArray fix)
- entity_metadata 1.8 (entityMetadataLoop mergeCompareTo)
- spawn_entity_living 1.8 (entityMetadata mergeCompareTo)

These ensure packets that were previously broken stay working.
2026-08-05 19:36:38 +02:00
OpenCode ac1b298989 fix: implement topBitSetTerminatedArray, fix nbt TAG_End, fix entity_equipment
- Implement topBitSetTerminatedArray decoder/encoder with MSB continuation
- Fix nbt.Tag.Decode to handle TAG_End at root level (fixes 1.8 slot NBT)
- Remove 228 now-passing decode failure tests, keep 10 still failing
- EntityEquipment now works correctly across all versions
2026-08-05 19:30:18 +02:00
OpenCode 1d8f70c7fd test: fix decode failure tests - remove 200 now-passing, fix format strings
Generator fixes resolved most decode failures. 200 tests removed
(packets now decode correctly), 38 still test known failures.
Also fixed bytes.NewBuffer->bytes.NewReader and malformed format
strings in remaining old tests.
2026-08-05 19:05:03 +02:00
OpenCode 40b584dec4 test: add 26.2 replay decode failure tests from live capture
29 tests generated from live 26.2 clientbound capture via tcpflow.
6076 packets captured, 35 decode failures (0.58%), 0 serverbound failures.
2026-08-05 19:01:37 +02:00
OpenCode eb83786f9a fix: resolve parameterized $compareTo types and fix array count type
- VisitNameAndData: return any instead of named struct when mergeCompareTo
  resolves $compareTo, fixing field type mismatches for switch/container types
- ContainerCompareTo: traverse anon/bitfield fields for compareTo resolution,
  fixes entityMetadata 'field not found' errors
- Array.Count: change from string to any to handle numeric count values
- ArrayEncoder: fix nil check to correctly write length prefix for arrays
- ArrayDecoder: use fmt.Sprint for safe Count conversion
2026-08-05 18:33:39 +02:00
OpenCode fa70ea36c6 fix: print_replay test generation & raw_to_tmcpr config state
- Fix SaveUnCodeAbleAsTest using wrong package name (1.8.9 vs v1_8)
- Fix test template using bytes.Buffer instead of bytes.NewReader
- Tests now fail when decode SUCCEEDS (bug is fixed)
- Add config state support to raw_to_tmcpr with -config flag
- Fix mca_to_tmcpr -world flag being ignored
2026-08-05 17:43:26 +02:00
OpenCode 7c978e1a7e fix: raw_to_tmcpr Configuration state + mca_to_tmcpr -world flag
- Add -config flag and Configuration state support to raw_to_tmcpr
  (required for Minecraft 1.20.2+ protocol >= 764)
- Add 'config' as valid initial state option
- Fix mca_to_tmcpr -world flag being ignored (was hardcoded dev path)
- Add TMCPR replay test data from live 1.8 capture
2026-08-05 17:36:49 +02:00
OpenCode 44bfa2280c test: add TMCPR replay test data from live 1.8 capture 2026-08-05 17:36:38 +02:00
OpenCode a54b066012 fix: preserve original hostname in handshake (DNS resolves to IP) 2026-08-05 16:06:08 +02:00
OpenCode 4b278b7ee3 fix: multiple bugfixes
- Fix data race: use atomic.Bool for running in server.go
- Fix busy loop in timer.go: use time.After when idle
- Fix division by zero in print_replay
- Fix silently swallowed errors in proto_generator
- Fix suppressed error in native_encoder
- Delete unused registry_data_hunter
2026-08-05 14:50:10 +02:00
OpenCode 0ed96837bd feat: add 1.16.5 protocol support
- Add 1.16.5 minecraft-data
- Add v1_16_5 proto_generated code
- Add OnSuccess1_16_5 handler in client/login.go
- Update proto_generator to include 1.16.5
- Update download_minecraft_data.sh
2026-08-05 11:13:58 +02:00
Admin Else c911f95665 strom: add 1.14.4 protocol support, extend legacy range to 1.14.4
- Add minecraft-data for 1.14.4 (protocol 498)
- Generate proto_generated/v1_14_4
- Extend legacy RegisterUntil range from 1.12.2 to 1.14.4
- Update download_minecraft_data.sh to use admin-else fork
  and include all supported versions
2026-08-05 10:29:07 +02:00
Admin Else f645f3d78d strom: consolidate identical handlers to single v1_8-based versions
For types identical across all versions (Compress, Disconnect, Status,
Pong), use a single handler at v1_8 registered to 26.2 instead of
per-version duplicates. For types that differ (Encrypt has extra
ShouldAuthenticate field in newer versions, Success has different
Uuid type), keep dual-range registrations.
2026-08-04 22:31:06 +02:00
Admin Else 1001c809e5 strom: fix RegisterUntilLow to panic on reverse range, use dual-range registrations
- RegisterUntilLow now panics if startIndex > endIndex (programmer
  must address version incompatibility explicitly, not silently skip)
- Replace per-version RegisterCritical handlers with dual-range
  RegisterUntil: modern range (v1_21_8->latest) + legacy range (v1_8->1.12.2)
- Remove v1_12_2 handler duplicates (covered by upward range from v1_8)
- Move legacy chat handling into chat.Module.SendMessage (protocol<764
  uses v1_8.PlayToServerPacketChat instead of v1_21_11)
- Skip chat signing init for pre-1.19 versions
2026-08-04 22:16:34 +02:00
Admin Else 1e6ce06fb0 strom: add 1.12.2 protocol support and legacy login/status handlers
- Add minecraft-data for 1.12.2 (protocol 340)
- Generate proto_generated/v1_12_2
- Add v1_12_2 legacy handlers to client.Login (OnDisconnect,
  OnCompress, OnSuccess) and client.Status (OnStatus, OnPong)
- Same pattern as v1_8: RegisterUntilLatest only registers
  upward, so legacy versions need explicit RegisterCritical handlers
2026-08-04 22:01:06 +02:00
Admin Else acb5fe8d90 port messenger to more versions 2026-08-04 19:28:43 +02:00
Admin Else d9bca7e517 strom: fix generator for pointer-receiver Encode, use nbt.Tag for named NBT
- Delete raw_capture subcommand (use tcpflow + raw-to-tmcpr instead)
- Fix DefaultEncoder to use temp variable for non-addressable value encoding,
  eliminating manual post-generation patches
- Map nbt and optionalNbt types to nbt.Tag (named NBT) instead of nbt.Anon
  (anonymous NBT) — 1.8 uses named NBT with root tag names
2026-08-04 16:40:47 +02:00
Admin Else b162d0d401 strom: add 1.8 protocol support, raw-to-tmcpr, disable raw-capture
- Add minecraft-data for version 1.8 (protocol 47)
- Generate proto_generated/v1_8 from 1.8 protocol.json
- Fix generator compatibility: missing CompareTo natives (i16, i32, u16, u32,
  i64, string, nbt, optionalNbt), parameterized type placeholder handling ()
- Add raw-to-tmcpr subcommand: converts raw tcpflow captures to TMCPR
  with zlib decompression and state-aware compression threshold tracking
- Extend print-replay: 1.8 state transitions (success->Play, login_start->Play,
  handshake/status initial states, set_protocol NextState detection)
- Comment out broken raw-capture subcommand (use tcpflow instead)
- Fix nbt.Anon Encode/Decode on value receivers
2026-08-04 16:10:15 +02:00
Admin Else 3273244c42 format 2026-08-02 20:21:15 +02:00
adman f579645b88 client: add StatusRawWithVersion for version-aware status pings 2026-07-31 19:34:16 +02:00
adman 33754d7c71 server: guard against nil KnownPacks in ServeConfig 2026-07-31 15:49:05 +02:00
adman 8bd54a04f2 client: add ConnectWithConn, WithConn, WithDialer, LoginRawAddr
- ConnectWithConn wraps an existing net.Conn into a versioned proto.Conn
- DialFunc is a context-aware dial function type
- WithConn uses a pre-established net.Conn (version required, no DNS)
- WithDialer replaces net.Dialer with a custom dial function
- LoginRawAddr accepts an explicit handshake host address
- Login() wired to support all three connection modes
2026-07-31 14:30:25 +02:00
adman 492dae8e83 Add WithIgnoreConfig option to skip CONFIGURATION auto-completion 2026-07-31 12:10:32 +02:00
adman d9543de951 add check for bad servers 2026-07-30 02:40:43 +02:00
adman f1f5374a5c more context 2026-07-30 02:36:37 +02:00
adman 0d6b6e1ab9 docs: add godoc comments to all exported functions and methods 2026-07-30 00:20:55 +02:00
adman 56c97a2b3f docs: add API reference for all user-facing packages 2026-07-30 00:10:57 +02:00
adman 9063a0328d fix: make RegisterCritical variadic for API consistency with RegisterCriticalUntilLatest 2026-07-30 00:05:39 +02:00
237 changed files with 432359 additions and 3931 deletions
-6
View File
@@ -1,6 +0,0 @@
**/*_test.go export-ignore
**/testdata export-ignore
*.zip filter=lfs diff=lfs merge=lfs -text
*.tmcpr filter=lfs diff=lfs merge=lfs -text
*.mcpr filter=lfs diff=lfs merge=lfs -text
*.mca filter=lfs diff=lfs merge=lfs -text
+28
View File
@@ -0,0 +1,28 @@
name: Go
on:
push:
branches: ["master"]
pull_request:
branches: ["master"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.26.2"
- name: Build
run: go build -v ./...
- name: Vet
run: go vet -v ./...
- name: Test
run: go test -v ./...
+2 -1
View File
@@ -1,4 +1,5 @@
.devres/
.idea/
.failed_packets/
.vscode/
.vscode/proto_generator
proto_generator
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"log/slog"
"os"
"github.com/admin-else/strom/mc/api"
"git.anygate.cloud/anygatecloud/strom/mc/api"
)
var cmd = flag.NewFlagSet("api", flag.ContinueOnError)
+1 -1
View File
@@ -1,6 +1,6 @@
package cmd_util
import "github.com/admin-else/strom/mc/api"
import "git.anygate.cloud/anygatecloud/strom/mc/api"
func Account(s string) (a *api.Account, err error) {
if len(s) > 16 {
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"os"
"slices"
mcdata "github.com/admin-else/strom/mc/data"
"github.com/admin-else/strom/mc/proto_generated"
"github.com/admin-else/strom/mc/util"
mcdata "git.anygate.cloud/anygatecloud/strom/mc/data"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated"
"git.anygate.cloud/anygatecloud/strom/mc/util"
)
// strom data 1.21.11 blocks id 0 name => air
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"log/slog"
"os"
"github.com/admin-else/strom/mc/level/anvil"
"github.com/admin-else/strom/mc/nbt"
"git.anygate.cloud/anygatecloud/strom/mc/level/anvil"
"git.anygate.cloud/anygatecloud/strom/mc/nbt"
)
var (
+17 -17
View File
@@ -9,21 +9,21 @@ import (
"runtime/debug"
"slices"
"github.com/admin-else/strom/cmd/strom/api"
"github.com/admin-else/strom/cmd/strom/data"
"github.com/admin-else/strom/cmd/strom/extract_mca"
"github.com/admin-else/strom/cmd/strom/mca_to_tmcpr"
"github.com/admin-else/strom/cmd/strom/messenger"
"github.com/admin-else/strom/cmd/strom/offline_uuid"
"github.com/admin-else/strom/cmd/strom/packet_info"
"github.com/admin-else/strom/cmd/strom/packet_inspector"
"github.com/admin-else/strom/cmd/strom/print_nbt"
"github.com/admin-else/strom/cmd/strom/print_replay"
"github.com/admin-else/strom/cmd/strom/raw_capture"
"github.com/admin-else/strom/cmd/strom/registry_data_hunter"
"github.com/admin-else/strom/cmd/strom/serve_tmcpr"
"github.com/admin-else/strom/cmd/strom/serve_world"
"github.com/admin-else/strom/cmd/strom/status"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/api"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/data"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/extract_mca"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/mca_to_tmcpr"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/messenger"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/offline_uuid"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/packet_info"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/packet_inspector"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/print_nbt"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/print_replay"
// "git.anygate.cloud/anygatecloud/strom/cmd/strom/raw_capture" // removed: use tcpflow instead for raw TCP capture
"git.anygate.cloud/anygatecloud/strom/cmd/strom/raw_to_tmcpr"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/serve_tmcpr"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/serve_world"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/status"
)
var ExpectedASubcommandErr = errors.New("expected a subcommand")
@@ -61,8 +61,8 @@ var subcommands = map[string]func(args []string) error{
"extract-mca": extract_mca.Run,
"data": data.Run,
"print-replay": print_replay.Run,
"raw-capture": raw_capture.Run,
"registry-data-hunter": registry_data_hunter.Run,
// "raw-capture": raw_capture.Run, // removed: use tcpflow instead for raw TCP capture, then raw-to-tmcpr
"raw-to-tmcpr": raw_to_tmcpr.Run,
"serve-world": serve_world.Run,
"mca-to-tmcpr": mca_to_tmcpr.Run,
"serve-tmcpr": serve_tmcpr.Run,
+8 -7
View File
@@ -6,13 +6,14 @@ import (
"fmt"
"log/slog"
"os"
"path/filepath"
"github.com/admin-else/strom/mc/level"
"github.com/admin-else/strom/mc/level/anvil"
"github.com/admin-else/strom/mc/nbt"
"github.com/admin-else/strom/mc/proto/replay"
"github.com/admin-else/strom/mc/proto_generated/v1_21_11"
"github.com/admin-else/strom/mc/util"
"git.anygate.cloud/anygatecloud/strom/mc/level"
"git.anygate.cloud/anygatecloud/strom/mc/level/anvil"
"git.anygate.cloud/anygatecloud/strom/mc/nbt"
"git.anygate.cloud/anygatecloud/strom/mc/proto/replay"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_11"
"git.anygate.cloud/anygatecloud/strom/mc/util"
)
var (
@@ -51,7 +52,7 @@ func GetChunkFromMca(x, z int32, version string) (b []byte, err error) {
z += anvil.ChunksWidthRegionFile
}
f, err := os.Open(fmt.Sprintf("./.devres/anvil_testdata/securechattestworld/region/r.%v.%v.mca", xmca, zmca))
f, err := os.Open(filepath.Join(*worldPath, "region", fmt.Sprintf("r.%v.%v.mca", xmca, zmca)))
if err != nil {
return
}
+48 -18
View File
@@ -7,15 +7,16 @@ import (
"strconv"
"strings"
"github.com/admin-else/strom/cmd/strom/cmd_util"
"github.com/admin-else/strom/mc/bot/chat"
"github.com/admin-else/strom/mc/bot/keepalive"
"github.com/admin-else/strom/mc/bot/world"
"github.com/admin-else/strom/mc/client"
"github.com/admin-else/strom/mc/data"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_generated/v1_21_11"
"git.anygate.cloud/anygatecloud/strom/cmd/strom/cmd_util"
"git.anygate.cloud/anygatecloud/strom/mc/bot/chat"
"git.anygate.cloud/anygatecloud/strom/mc/bot/keepalive"
"git.anygate.cloud/anygatecloud/strom/mc/bot/world"
"git.anygate.cloud/anygatecloud/strom/mc/client"
"git.anygate.cloud/anygatecloud/strom/mc/data"
"git.anygate.cloud/anygatecloud/strom/mc/event"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_11"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_8"
)
func stror(a, b string) string {
@@ -29,12 +30,14 @@ var (
cmd = flag.NewFlagSet("status", flag.ContinueOnError)
connectToFlag = cmd.String("addr", "", "server address to connect to")
accFlag = cmd.String("acc", stror(os.Getenv("STROM_ACC"), "strom_messenger"), "the name to use if longer will be treated as ygg token")
versionFlag = cmd.String("version", "26.2", "minecraft version to use (e.g. 1.8, 1.21.11)")
)
type Messenger struct {
*proto.Conn
chat *chat.Module
world *world.Module
legacy bool
}
func (m *Messenger) OnChat(e *v1_21_11.PlayToClientPacketPlayerChat) (err error) {
@@ -52,15 +55,27 @@ func (m *Messenger) OnChatSystem(e *v1_21_11.PlayToClientPacketSystemChat) (err
return
}
func (m *Messenger) OnChatLegacy(e *v1_8.PlayToClientPacketChat) (err error) {
m.Log.Info("chat", "m", e.Message)
return
}
func (m *Messenger) OnStdin(e event.Stdin) (err error) {
input := strings.TrimSpace(e.Val)
if strings.HasPrefix(input, ">say ") {
return m.chat.SendMessage(strings.TrimSpace(strings.TrimPrefix(input, ">say")))
return m.sendChat(strings.TrimSpace(strings.TrimPrefix(input, ">say")))
}
if strings.HasPrefix(input, ">getblock ") {
if !m.legacy && strings.HasPrefix(input, ">getblock ") {
return m.handleGetBlock(strings.TrimSpace(strings.TrimPrefix(input, ">getblock")))
}
return m.chat.SendMessage(input)
return m.sendChat(input)
}
func (m *Messenger) sendChat(message string) (err error) {
if m.legacy {
return m.Send(&v1_8.PlayToServerPacketChat{Message: message})
}
return m.chat.SendMessage(message)
}
func (m *Messenger) handleGetBlock(args string) (err error) {
@@ -105,30 +120,45 @@ func Run(args []string) (err error) {
if err != nil {
return
}
c, err := client.Login(*connectToFlag, acc)
c, err := client.Login(*connectToFlag, acc, client.WithVersion(*versionFlag))
if err != nil {
return
}
defer c.Close()
chatMod, err := chat.Start(c, acc)
isLegacy := c.ProtocolVersion < 764
var chatMod *chat.Module
if !isLegacy {
chatMod, err = chat.Start(c, acc)
if err != nil {
return
}
// Shareable world storage. Other bots can subscribe to the same World.
w := world.NewWorld(c.Version, -64, 384)
}
m := &Messenger{
Conn: c,
chat: chatMod,
world: world.Start(c, w),
legacy: isLegacy,
}
if !isLegacy {
w := world.NewWorld(c.Version, -64, 384)
m.world = world.Start(c, w)
}
event.StartListingStdin(m.Loop)
m.Register(m.OnStdin)
if isLegacy {
m.Register(m.OnChatLegacy)
} else {
m.RegisterUntilLatest(m.OnChat, m.OnChatUnsigned, m.OnChatSystem)
}
if !isLegacy {
keepalive.Start(m.Conn)
}
return m.StartConn()
}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"flag"
"fmt"
"github.com/admin-else/strom/mc/crypto"
"git.anygate.cloud/anygatecloud/strom/mc/crypto"
)
var cmd = flag.NewFlagSet("offline-uuid", flag.ContinueOnError)
+4 -4
View File
@@ -5,10 +5,10 @@ import (
"fmt"
"strconv"
"github.com/admin-else/strom/mc/data"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated"
"git.anygate.cloud/anygatecloud/strom/mc/data"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated"
)
var cmd = flag.NewFlagSet("packet-info", flag.ContinueOnError)
+11 -10
View File
@@ -7,15 +7,15 @@ import (
"os"
"time"
"github.com/admin-else/strom/mc/api"
"github.com/admin-else/strom/mc/client"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/nbt"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_11"
"github.com/admin-else/strom/mc/server"
"github.com/admin-else/strom/mc/text"
"git.anygate.cloud/anygatecloud/strom/mc/api"
"git.anygate.cloud/anygatecloud/strom/mc/client"
"git.anygate.cloud/anygatecloud/strom/mc/event"
"git.anygate.cloud/anygatecloud/strom/mc/nbt"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_11"
"git.anygate.cloud/anygatecloud/strom/mc/server"
"git.anygate.cloud/anygatecloud/strom/mc/text"
)
var Cmd = flag.NewFlagSet("packet-inspector", flag.ContinueOnError)
@@ -26,6 +26,7 @@ var Token = Cmd.String("token", "", "token to use")
var TargetAddr = Cmd.String("addr", "127.0.0.1:25565", "address to connect to")
var ListenAddr = Cmd.String("listen", "127.0.0.1:25566", "address to listen on")
var TrueForward = Cmd.Bool("true-forward", false, "forward packets without modification -name and custom server status wont work")
var Version = Cmd.String("protocol-version", "", "protocol version to use; empty for auto")
type Proxy struct {
Client, Servee *proto.Conn
@@ -182,7 +183,7 @@ func Run(args []string) (err error) {
if err != nil {
return
}
c, err := client.Connect(nil, *TargetAddr, "")
c, err := client.Connect(nil, *TargetAddr, *Version)
if err != nil {
return
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"fmt"
"os"
"github.com/admin-else/strom/mc/nbt"
"git.anygate.cloud/anygatecloud/strom/mc/nbt"
)
var (
+4 -4
View File
@@ -4,15 +4,15 @@ import (
"bytes"
"testing"
generated "github.com/admin-else/strom/mc/proto_generated/%v"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/%v"
)
// Error: %v
func TestFailedPacket%10X(t *testing.T) {
p := &generated.%v{}
b := bytes.NewBuffer(%#v)
b := bytes.NewReader(%#v)
err := p.Decode(b)
if err != nil {
t.Fatal(err)
if err == nil {
t.Fatalf("expected decode error but got nil")
}
}
+44 -27
View File
@@ -15,9 +15,8 @@ import (
"reflect"
"strings"
"github.com/admin-else/strom/mc/data"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
)
var (
@@ -25,12 +24,10 @@ var (
FileFlag = cmd.String("file", "", "The tmcpr file to print")
ProtocolVersion = cmd.Int("protocol", -1, "The protocol version")
CreateTestsPath = cmd.String("create-tests", "", "")
StateFlag = cmd.String("state", "login", "Initial state: login, config, play")
StateFlag = cmd.String("state", "login", "Initial state: handshake, login, config, status, play")
DirectionFlag = cmd.String("direction", "clientbound", "Packet direction: clientbound (ToClient) or serverbound (ToServer)")
)
// TODO: maybe use the proto replay api
//go:embed failed_packet.go.tmpl
var TestSrcF string
@@ -46,11 +43,8 @@ func SaveUnCodeAbleAsTest(packet *proto.UnCodablePacket) (err error) {
return
}
ret, err := data.LookUpVersionByProtocolVersion(packet.Info.ProtocolVersion)
if err != nil {
return
}
goPackage := "v" + strings.ReplaceAll(ret.MinecraftVersion, ".", "_")
typeStr := reflect.TypeOf(packet.Info.Type).String()
goPackage := typeStr[1:strings.LastIndex(typeStr, ".")]
typeName := reflect.TypeOf(packet.Info.Type).Elem().Name()
src := fmt.Sprintf(TestSrcF, goPackage, packet.Err, h, typeName, packet.Data)
@@ -106,22 +100,6 @@ func UnpackPacket(r io.Reader) (packet proto_base.EncodeDecodeAble, i proto_base
packet = &proto.UnCodablePacket{Err: proto.BadPacketIdErr, Data: packetData, Info: i}
return
}
switch direction {
case proto_base.ToClient:
switch i.Name {
case "success":
state = proto_base.Configuration
case "finish_configuration":
state = proto_base.Play
}
case proto_base.ToServer:
switch i.Name {
case "login_acknowledged":
state = proto_base.Configuration
case "finish_configuration":
state = proto_base.Play
}
}
packet = reflect.New(reflect.TypeOf(i.Type).Elem()).Interface().(proto_base.EncodeDecodeAble)
err = packet.Decode(b)
if err != nil {
@@ -132,9 +110,40 @@ func UnpackPacket(r io.Reader) (packet proto_base.EncodeDecodeAble, i proto_base
packet = &proto.UnCodablePacket{Err: proto.PacketNotFullyDecodedErr, Data: packetData[indexafterid:], Info: i}
return
}
trackState(packet, i)
return
}
func trackState(packet proto_base.EncodeDecodeAble, i proto_base.PacketInfo) {
switch i.Name {
case "set_protocol":
v := reflect.ValueOf(packet).Elem()
nsField := v.FieldByName("NextState")
if nsField.IsValid() && nsField.Kind() == reflect.Int32 {
switch nsField.Int() {
case 1:
state = proto_base.Status
case 2:
state = proto_base.Login
}
}
case "login_start":
if int32(*ProtocolVersion) <= 47 {
state = proto_base.Play
}
case "success":
if int32(*ProtocolVersion) >= 764 {
state = proto_base.Configuration
} else {
state = proto_base.Play
}
case "finish_configuration":
state = proto_base.Play
case "login_acknowledged":
state = proto_base.Configuration
}
}
func Run(args []string) (err error) {
err = cmd.Parse(args)
if err != nil {
@@ -147,12 +156,16 @@ func Run(args []string) (err error) {
return fmt.Errorf("no file specified")
}
switch *StateFlag {
case "handshake":
state = proto_base.Handshaking
case "login":
state = proto_base.Login
case "config":
state = proto_base.Configuration
case "play":
state = proto_base.Play
case "status":
state = proto_base.Status
default:
return fmt.Errorf("unknown state: %s", *StateFlag)
}
@@ -193,6 +206,10 @@ func Run(args []string) (err error) {
}
totalPackets++
}
if totalPackets > 0 {
fmt.Printf("Total packets: %d, failed packets: %d, %%failed: %.2f%%\n", totalPackets, failedPackets, float64(failedPackets)/float64(totalPackets)*100)
} else {
fmt.Printf("Total packets: %d, failed packets: %d\n", totalPackets, failedPackets)
}
return
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Error: unexpected EOF
func TestFailedPacket0F8B37C94207F7BF(t *testing.T) {
p := &generated.PlayToClientPacketUpdateTime{}
b := bytes.NewReader([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x42, 0x0})
err := p.Decode(b)
if err == nil {
t.Fatalf("expected decode error but got nil")
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Error: unexpected EOF
func TestFailedPacket6C9AD835672C5C51(t *testing.T) {
p := &generated.PlayToClientPacketUpdateTime{}
b := bytes.NewReader([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0xde, 0x0})
err := p.Decode(b)
if err == nil {
t.Fatalf("expected decode error but got nil")
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Error: unexpected EOF
func TestFailedPacketA5D61E1C0F23E7FA(t *testing.T) {
p := &generated.PlayToClientPacketUpdateTime{}
b := bytes.NewReader([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x56, 0x0})
err := p.Decode(b)
if err == nil {
t.Fatalf("expected decode error but got nil")
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Error: unexpected EOF
func TestFailedPacketCAA58159889F7E8A(t *testing.T) {
p := &generated.PlayToClientPacketUpdateTime{}
b := bytes.NewReader([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x2e, 0x0})
err := p.Decode(b)
if err == nil {
t.Fatalf("expected decode error but got nil")
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Error: unexpected EOF
func TestFailedPacketD18FC4C0B2DF2972(t *testing.T) {
p := &generated.PlayToClientPacketUpdateTime{}
b := bytes.NewReader([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0xf2, 0x0})
err := p.Decode(b)
if err == nil {
t.Fatalf("expected decode error but got nil")
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Error: unexpected EOF
func TestFailedPacketE81E82016DB04F28(t *testing.T) {
p := &generated.PlayToClientPacketUpdateTime{}
b := bytes.NewReader([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x6, 0x0})
err := p.Decode(b)
if err == nil {
t.Fatalf("expected decode error but got nil")
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Error: unexpected EOF
func TestFailedPacketFE935CF2E584C649(t *testing.T) {
p := &generated.PlayToClientPacketUpdateTime{}
b := bytes.NewReader([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x1a, 0x0})
err := p.Decode(b)
if err == nil {
t.Fatalf("expected decode error but got nil")
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Decode regression: recipe_book_add (26.2) - SlotDisplay type fix
func TestRegressionPacket25D845B5D0023D22(t *testing.T) {
p := &generated.PlayToClientPacketRecipeBookAdd{}
b := bytes.NewReader([]byte{0x1, 0xbe, 0x2, 0x1, 0x2, 0x2, 0x4, 0x6, 0x10, 0x6d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x3a, 0x70, 0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x6, 0x10, 0x6d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x3a, 0x70, 0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x6, 0x10, 0x6d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x3a, 0x70, 0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x6, 0x10, 0x6d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x3a, 0x70, 0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x5, 0xe8, 0x2, 0x1, 0x0, 0x0, 0x4, 0xe8, 0x2, 0x0, 0x3, 0x1, 0x4, 0x0, 0x10, 0x6d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x3a, 0x70, 0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x0, 0x10, 0x6d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x3a, 0x70, 0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x0, 0x10, 0x6d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x3a, 0x70, 0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x0, 0x10, 0x6d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x3a, 0x70, 0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x2, 0x1})
err := p.Decode(b)
if err != nil {
t.Fatalf("regression: decode failed: %v", err)
}
}
@@ -0,0 +1,17 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Decode regression: declare_commands (26.2) - bitfield + extraNodeData fix
func TestRegressionPacket78C731784E6E834A(t *testing.T) {
p := &generated.PlayToClientPacketDeclareCommands{}
b := bytes.NewReader([]byte{0x1a, 0x0, 0xa, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x1, 0x1, 0xb, 0x2, 0x6d, 0x65, 0x5, 0x1, 0xc, 0x4, 0x68, 0x65, 0x6c, 0x70, 0x5, 0x1, 0xd, 0x4, 0x6c, 0x69, 0x73, 0x74, 0x1, 0x1, 0xe, 0x3, 0x6d, 0x73, 0x67, 0x9, 0x0, 0x4, 0x4, 0x74, 0x65, 0x6c, 0x6c, 0x9, 0x0, 0x4, 0x1, 0x77, 0x1, 0x2, 0xf, 0x10, 0x6, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x1, 0x1, 0x11, 0x7, 0x74, 0x65, 0x61, 0x6d, 0x6d, 0x73, 0x67, 0x9, 0x0, 0x8, 0x2, 0x74, 0x6d, 0x1, 0x1, 0x12, 0x7, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x6, 0x0, 0x6, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x14, 0x6, 0x0, 0x7, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5, 0x2, 0x5, 0x0, 0x5, 0x75, 0x75, 0x69, 0x64, 0x73, 0x2, 0x1, 0x13, 0x7, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x6, 0x2, 0x1, 0x1, 0x14, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1, 0x1, 0x15, 0x4, 0x72, 0x6f, 0x6c, 0x6c, 0x6, 0x0, 0x7, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x14, 0x16, 0x2, 0x16, 0x17, 0x9, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x14, 0x6d, 0x69, 0x6e, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x3a, 0x61, 0x73, 0x6b, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x6, 0x0, 0x7, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x14, 0x6, 0x0, 0x5, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x27, 0x6, 0x0, 0x5, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x27, 0x1, 0x1, 0x18, 0x3, 0x61, 0x64, 0x64, 0x1, 0x1, 0x19, 0x3, 0x73, 0x65, 0x74, 0x6, 0x0, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3, 0x0, 0x6, 0x0, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3, 0x0, 0x0})
err := p.Decode(b)
if err != nil {
t.Fatalf("regression: decode failed: %v", err)
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_8"
)
// Decode regression: spawn_entity_living (1.8) - entityMetadata mergeCompareTo
func TestRegressionPacket2B76AF8B937B1E8F(t *testing.T) {
p := &generated.PlayToClientPacketSpawnEntityLiving{}
b := bytes.NewReader([]byte{0x4c, 0x65, 0xff, 0xff, 0xed, 0x66, 0x0, 0x0, 0x7, 0xe0, 0x0, 0x0, 0x29, 0xe6, 0x91, 0x0, 0x91, 0x0, 0x0, 0xfd, 0x8d, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1, 0x2c, 0x82, 0x0, 0x12, 0x4, 0x3, 0x0, 0x4, 0x0, 0x66, 0x41, 0x20, 0x0, 0x0, 0x47, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x9, 0x0, 0xc, 0x0, 0xf, 0x0, 0x7f})
err := p.Decode(b)
if err != nil {
t.Fatalf("regression: decode failed: %v", err)
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_8"
)
// Decode regression: entity_equipment (1.8) - nbt TAG_End fix
func TestRegressionPacket0C20C77EA68496BD(t *testing.T) {
p := &generated.PlayToClientPacketEntityEquipment{}
b := bytes.NewReader([]byte{0x89, 0x16, 0x0, 0x0, 0x1, 0x5, 0x1, 0x0, 0x0, 0x0})
err := p.Decode(b)
if err != nil {
t.Fatalf("regression: decode failed: %v", err)
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_8"
)
// Decode regression: entity_metadata (1.8) - entityMetadataLoop mergeCompareTo
func TestRegressionPacketDF2DF88561529208(t *testing.T) {
p := &generated.PlayToClientPacketEntityMetadata{}
b := bytes.NewReader([]byte{0x69, 0x0, 0x0, 0x21, 0x1, 0x2c, 0x82, 0x0, 0x3, 0x0, 0x4, 0x0, 0x66, 0x40, 0x80, 0x0, 0x0, 0x47, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x9, 0x0, 0xc, 0x0, 0xf, 0x0, 0x7f})
err := p.Decode(b)
if err != nil {
t.Fatalf("regression: decode failed: %v", err)
}
}
@@ -0,0 +1,18 @@
package failed_packets_test
import (
"bytes"
"testing"
generated "git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
)
// Decode regression: entity_equipment (26.2) - topBitSetTerminatedArray
func TestRegressionPacket1D0089BBE86A1648(t *testing.T) {
p := &generated.PlayToClientPacketEntityEquipment{}
b := bytes.NewReader([]byte{0x81, 0x2, 0x0, 0x1, 0x9a, 0x7, 0x0, 0x0})
err := p.Decode(b)
if err != nil {
t.Fatalf("regression: decode failed: %v", err)
}
}
-253
View File
@@ -1,253 +0,0 @@
package raw_capture
import (
"flag"
"fmt"
"log/slog"
"os"
"time"
"github.com/admin-else/strom/mc/api"
"github.com/admin-else/strom/mc/client"
"github.com/admin-else/strom/mc/data"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto/replay"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_11"
"github.com/admin-else/strom/mc/server"
"github.com/admin-else/strom/mc/text"
)
var Cmd = flag.NewFlagSet("raw-capture", flag.ContinueOnError)
var OfflineNameFlag = Cmd.String("name", "raw_capture", "offline player name")
var Token = Cmd.String("token", "", "token to use")
var TargetAddr = Cmd.String("addr", "127.0.0.1:25565", "address to connect to")
var ListenAddr = Cmd.String("listen", "127.0.0.1:25566", "address to listen on")
var ClientboundFile = Cmd.String("clientbound-file", "clientbound.tmcpr", "file to write clientbound packets to")
var ServerboundFile = Cmd.String("serverbound-file", "serverbound.tmcpr", "file to write serverbound packets to")
var Version = Cmd.String("version", "", "client protocol version (e.g. 26.1); if empty, detect from server status")
var StatusResponse = server.StatusResponse{
Version: server.StatusResponseVersion{
Name: text.Pretty("STROM raw-capture"),
Protocol: 0,
},
Players: server.StatusResponsePlayers{},
Description: text.Pretty("STROM raw-capture proxy"),
Favicon: "",
EnforcesSecureChat: false,
}
type Proxy struct {
Client, Servee *proto.Conn
clientboundFile *os.File
serverboundFile *os.File
clientboundWriter *replay.Writer
serverboundWriter *replay.Writer
startTime time.Time
}
func (p *Proxy) Start() (err error) {
p.startTime = time.Now()
p.Client.RegisterCritical(p.OnAnything)
p.Servee.RegisterCritical(p.OnAnything)
p.Client.RegisterCriticalUntilLatest(p.OnCompress)
p.Servee.RegisterCriticalUntilLatest(p.OnHandshake)
p.Servee.RegisterCriticalUntilLatest(p.OnLoginAcknowledged)
p.Servee.RegisterCriticalUntilLatest(p.OnFinishConfiguration)
errChan := make(chan error)
go func() {
errChan <- p.Client.StartConn()
}()
go func() {
errChan <- p.Servee.StartConn()
}()
err = <-errChan
return
}
func (p *Proxy) timestamp() uint32 {
return uint32(time.Since(p.startTime).Milliseconds())
}
func (p *Proxy) OnAnything(e event.Anything) (err error) {
packet, ok := e.Val.(proto_base.EncodeDecodeAble)
if !ok {
return
}
packetInfo, ok := proto.LookupPacketInfoByType(packet)
if !ok {
return
}
if packetInfo.Name == "encryption_begin" {
return fmt.Errorf("encryption requested by remote server; raw capture cannot continue")
}
switch packetInfo.Direction {
case proto_base.ToServer:
err = p.serverboundWriter.WritePacket(packet, p.timestamp())
if err != nil {
return
}
err = p.Client.Send(packet)
case proto_base.ToClient:
err = p.clientboundWriter.WritePacket(packet, p.timestamp())
if err != nil {
return
}
err = p.Servee.Send(packet)
}
return
}
func (p *Proxy) OnCompress(packet *v1_21_11.LoginToClientPacketCompress) (err error) {
err = p.clientboundWriter.WritePacket(packet, p.timestamp())
if err != nil {
return
}
err = p.Servee.Send(packet)
if err != nil {
return
}
p.Servee.SetCompressionThreshold(packet.Threshold)
p.Client.SetCompressionThreshold(packet.Threshold)
return event.DontForwardErr
}
func (p *Proxy) OnHandshake(packet *v1_21_11.HandshakingToServerPacketSetProtocol) (err error) {
state := proto_base.State(packet.NextState)
p.Servee.SetState(state)
return event.DontForwardErr
}
func (p *Proxy) OnLoginAcknowledged(packet *v1_21_11.LoginToServerPacketLoginAcknowledged) (err error) {
err = p.serverboundWriter.WritePacket(packet, p.timestamp())
if err != nil {
return
}
err = p.Client.Send(packet)
if err != nil {
return
}
p.Servee.SetState(proto_base.Configuration)
p.Client.SetState(proto_base.Configuration)
return event.DontForwardErr
}
func (p *Proxy) OnFinishConfiguration(packet *v1_21_11.ConfigurationToServerPacketFinishConfiguration) (err error) {
err = p.serverboundWriter.WritePacket(packet, p.timestamp())
if err != nil {
return
}
err = p.Client.Send(packet)
if err != nil {
return
}
p.Servee.SetState(proto_base.Play)
p.Client.SetState(proto_base.Play)
return event.DontForwardErr
}
func Run(args []string) (err error) {
err = Cmd.Parse(args)
if err != nil {
return
}
clientboundFile, err := os.Create(*ClientboundFile)
if err != nil {
return fmt.Errorf("create clientbound file: %w", err)
}
defer clientboundFile.Close()
serverboundFile, err := os.Create(*ServerboundFile)
if err != nil {
return fmt.Errorf("create serverbound file: %w", err)
}
defer serverboundFile.Close()
resolvedAddr, _, _, err := client.DoDNSChecked(nil, *TargetAddr, nil)
if err != nil {
return
}
var targetVersion string
var targetProtocol int32
if *Version == "" {
status, err := client.Status(nil, resolvedAddr)
if err != nil {
return fmt.Errorf("failed to detect server version: %w", err)
}
targetProtocol = status.Version.Protocol
versionInfo, err := data.LookUpVersionByProtocolVersion(targetProtocol)
if err != nil {
return fmt.Errorf("unknown protocol version %d: %w", targetProtocol, err)
}
targetVersion = versionInfo.MinecraftVersion
} else {
versionInfo, err := data.LookUpVersionByName(*Version)
if err != nil {
return fmt.Errorf("unknown version %s: %w", *Version, err)
}
targetVersion = versionInfo.MinecraftVersion
targetProtocol = versionInfo.Version
}
StatusResponse.Version.Name = text.Pretty("STROM raw-capture " + targetVersion)
StatusResponse.Version.Protocol = targetProtocol
StatusResponse.Description = text.Pretty(fmt.Sprintf("Raw capture proxy forwards to %s (%s)", resolvedAddr, targetVersion))
slog.Info("Starting raw capture", "listen", *ListenAddr, "target", resolvedAddr, "version", targetVersion, "protocol", targetProtocol, "clientbound", *ClientboundFile, "serverbound", *ServerboundFile)
err = server.StartServerWithOnConn(*ListenAddr, func(serveeConn *proto.Conn) (err error) {
proxy := &Proxy{
Servee: serveeConn,
clientboundFile: clientboundFile,
serverboundFile: serverboundFile,
clientboundWriter: replay.NewWriter(clientboundFile),
serverboundWriter: replay.NewWriter(serverboundFile),
}
acc := api.NewOfflineAccount(*OfflineNameFlag)
if *Token != "" {
acc, err = api.NewAccountFromYGG(*Token)
if err != nil {
return
}
}
_, err = server.ServeLogin(serveeConn, server.WithOtherAccount(acc), server.WithStatus(StatusResponse), server.WithoutOnlineMode(), server.WithoutEncryption())
if err != nil {
return
}
c, err := client.Connect(nil, resolvedAddr, targetVersion)
if err != nil {
return
}
defer c.Close()
err = client.LoginRaw(c, acc)
if err != nil {
return
}
proxy.Client = c
proxy.Client.AlwaysDecode = true
proxy.Servee.AlwaysDecode = true
return proxy.Start()
})
return
}
+256
View File
@@ -0,0 +1,256 @@
package raw_to_tmcpr
import (
"bytes"
"compress/zlib"
"errors"
"flag"
"fmt"
"io"
"os"
"time"
"git.anygate.cloud/anygatecloud/strom/mc/proto/replay"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
)
var Cmd = flag.NewFlagSet("raw-to-tmcpr", flag.ContinueOnError)
var ClientboundIn = Cmd.String("clientbound", "", "raw tcpflow file for clientbound (server->client) direction")
var ServerboundIn = Cmd.String("serverbound", "", "raw tcpflow file for serverbound (client->server) direction")
var ClientboundOut = Cmd.String("clientbound-out", "clientbound.tmcpr", "output TMCPR file for clientbound")
var ServerboundOut = Cmd.String("serverbound-out", "serverbound.tmcpr", "output TMCPR file for serverbound")
var ClientboundState = Cmd.String("clientbound-state", "login", "initial state for clientbound: handshake, login, config, status, play")
var ServerboundState = Cmd.String("serverbound-state", "handshake", "initial state for serverbound: handshake, login, config, status, play")
var UseConfig = Cmd.Bool("config", false, "use Configuration state transitions (for protocol >= 764, Minecraft 1.20.2+)")
type captureReader struct {
r io.Reader
out *replay.Writer
state proto_base.State
threshold int32
startTime time.Time
haveStartTime bool
direction proto_base.Direction
pendingThreshold int32
useConfig bool
}
func (cr *captureReader) setStartTime() {
if !cr.haveStartTime {
cr.startTime = time.Now()
cr.haveStartTime = true
}
}
func (cr *captureReader) timestamp() uint32 {
return uint32(time.Since(cr.startTime).Milliseconds())
}
func readPacketBytes(r io.Reader, threshold int32) ([]byte, error) {
packetLen, err := proto_base.DecodeVarInt(r)
if err != nil {
return nil, fmt.Errorf("read packet length: %w", err)
}
rawBytes := make([]byte, packetLen)
_, err = io.ReadFull(r, rawBytes)
if err != nil {
return nil, fmt.Errorf("read packet data: %w", err)
}
if threshold >= 0 {
buf := bytes.NewReader(rawBytes)
uncompressedLen, err := proto_base.DecodeVarInt(buf)
if err != nil {
return nil, fmt.Errorf("read uncompressed length: %w", err)
}
if uncompressedLen == 0 {
return io.ReadAll(buf)
} else {
zReader, err := zlib.NewReader(buf)
if err != nil {
return nil, fmt.Errorf("zlib reader: %w", err)
}
defer zReader.Close()
decompressed, err := io.ReadAll(zReader)
if err != nil {
return nil, fmt.Errorf("decompress: %w", err)
}
return decompressed, nil
}
}
return rawBytes, nil
}
func (cr *captureReader) trackState(packetBytes []byte) {
buf := bytes.NewReader(packetBytes)
packetId, err := proto_base.DecodeVarInt(buf)
if err != nil {
return
}
switch cr.state {
case proto_base.Handshaking:
if cr.direction == proto_base.ToServer && packetId == 0 {
_, err = proto_base.DecodeVarInt(buf) // protocol version
if err != nil {
return
}
_, err = proto_base.DecodeString(buf) // server address
if err != nil {
return
}
portBytes := make([]byte, 2)
_, err = io.ReadFull(buf, portBytes)
if err != nil {
return
}
nextState, err := proto_base.DecodeVarInt(buf)
if err != nil {
return
}
if nextState == 2 {
cr.state = proto_base.Login
} else if nextState == 1 {
cr.state = proto_base.Status
}
}
case proto_base.Login:
if cr.direction == proto_base.ToClient {
if packetId == 0x03 {
threshold, err := proto_base.DecodeVarInt(buf)
if err == nil {
cr.threshold = threshold
}
} else if packetId == 0x02 {
if cr.useConfig {
cr.state = proto_base.Configuration
} else {
cr.state = proto_base.Play
}
}
} else if cr.direction == proto_base.ToServer && packetId == 0 {
if cr.pendingThreshold >= 0 {
cr.threshold = cr.pendingThreshold
}
}
case proto_base.Configuration:
if cr.direction == proto_base.ToClient && packetId == 0x02 {
cr.state = proto_base.Play
}
case proto_base.Status:
case proto_base.Play:
}
}
func (cr *captureReader) process() (count int, err error) {
for {
packetBytes, err := readPacketBytes(cr.r, cr.threshold)
if err != nil {
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
return count, nil
}
return count, err
}
cr.setStartTime()
cr.trackState(packetBytes)
err = cr.out.WriteRaw(packetBytes, cr.timestamp())
if err != nil {
return count, fmt.Errorf("write TMCPR: %w", err)
}
count++
}
}
func Run(args []string) (err error) {
err = Cmd.Parse(args)
if err != nil {
return
}
if *ClientboundIn == "" && *ServerboundIn == "" {
return fmt.Errorf("at least one of -clientbound or -serverbound must be specified")
}
parseState := func(name string) (proto_base.State, error) {
switch name {
case "handshake":
return proto_base.Handshaking, nil
case "login":
return proto_base.Login, nil
case "config":
return proto_base.Configuration, nil
case "play":
return proto_base.Play, nil
case "status":
return proto_base.Status, nil
default:
return 0, fmt.Errorf("unknown state: %s (valid: handshake, login, config, status, play)", name)
}
}
var compressionThreshold int32 = -1
if *ClientboundIn != "" {
state, err := parseState(*ClientboundState)
if err != nil {
return err
}
compressionThreshold, err = processFile(*ClientboundIn, *ClientboundOut, state, proto_base.ToClient, -1, *UseConfig)
if err != nil {
return fmt.Errorf("clientbound: %w", err)
}
}
if *ServerboundIn != "" {
state, err := parseState(*ServerboundState)
if err != nil {
return err
}
_, err = processFile(*ServerboundIn, *ServerboundOut, state, proto_base.ToServer, compressionThreshold, *UseConfig)
if err != nil {
return fmt.Errorf("serverbound: %w", err)
}
}
return
}
func processFile(inPath, outPath string, initial proto_base.State, dir proto_base.Direction, initialThreshold int32, useConfig bool) (finalThreshold int32, err error) {
in, err := os.Open(inPath)
if err != nil {
return initialThreshold, fmt.Errorf("open input: %w", err)
}
defer in.Close()
out, err := os.Create(outPath)
if err != nil {
return initialThreshold, fmt.Errorf("create output: %w", err)
}
defer out.Close()
cr := &captureReader{
r: in,
out: replay.NewWriter(out),
state: initial,
threshold: -1,
direction: dir,
pendingThreshold: initialThreshold,
useConfig: useConfig,
}
if dir == proto_base.ToClient {
cr.threshold = initialThreshold
}
count, err := cr.process()
if err != nil {
return cr.threshold, err
}
fmt.Printf("%s: %d packets written to %s (threshold=%d)\n", inPath, count, outPath, cr.threshold)
return cr.threshold, nil
}
-152
View File
@@ -1,152 +0,0 @@
package registry_data_hunter
import (
"encoding/json"
"errors"
"log/slog"
"os"
"github.com/admin-else/strom/mc/api"
"github.com/admin-else/strom/mc/client"
"github.com/admin-else/strom/mc/data"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/nbt"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"github.com/admin-else/strom/mc/server"
"github.com/admin-else/strom/mc/text"
)
func wontFail[T any](v T, err error) T {
if err != nil {
panic(err)
}
return v
}
var (
Version = "1.21.11"
SaveAs = "data/registry/" + Version + ".nbt"
CompatibleProtocolVersion = wontFail(data.LookUpVersionByName(Version)).Version
FinishedConfigErr = errors.New("finished configuration")
)
var Status = wontFail(json.Marshal(server.StatusResponse{
Version: server.StatusResponseVersion{
Name: nil,
Protocol: CompatibleProtocolVersion,
},
Description: text.Pretty("Registry data hunter"),
}))
type Proxy struct {
Client, Servee *proto.Conn
Data *nbt.Tag
}
func (p *Proxy) OnAnything(e event.Anything) (err error) {
packet, ok := e.Val.(proto_base.EncodeDecodeAble)
if !ok {
return
}
packetInfo, ok := proto.LookupPacketInfoByType(packet)
if !ok {
return
}
switch packetInfo.Direction {
case proto_base.ToServer:
err = p.Client.Send(packet)
case proto_base.ToClient:
err = p.Servee.Send(packet)
}
return
}
func (p *Proxy) OnFinishConfiguration(_ *v1_21_8.ConfigurationToClientPacketFinishConfiguration) (err error) {
err = FinishedConfigErr
return
}
func (p *Proxy) OnSelectKnownPacks(data *v1_21_8.ConfigurationToClientPacketCommonSelectKnownPacks) (err error) {
var entries []any
for _, entry := range data.Packs {
e := map[string]any{"Namespace": entry.Namespace, "Id": entry.Id, "Version": entry.Version}
entries = append(entries, e)
}
p.Data.Value.(map[string]any)["KnownPacks"] = entries
return
}
func (p *Proxy) OnData(data *v1_21_8.ConfigurationToClientPacketRegistryData) (err error) {
d := p.Data.Value.(map[string]any)["Registries"].([]any)
var entries []any
for _, entry := range data.Entries {
if entry.Value != nil {
entries = append(entries, map[string]any{"TagType": entry.Key, "Value": entry.Value.Value})
} else {
entries = append(entries, map[string]any{"TagType": entry.Key})
}
}
d = append(d, map[string]any{"Id": data.Id, "Entries": entries})
p.Data.Value.(map[string]any)["Registries"] = d
return
}
func (p *Proxy) OnTags(data *v1_21_8.ConfigurationToClientPacketTags) (err error) {
var tags []any
for _, tag := range data.Tags {
var entries []any
for _, entry := range tag.Tags.Val {
entries = append(entries, map[string]any{"TagName": entry.TagName, "Entries": entry.Entries})
}
tags = append(tags, map[string]any{"TagType": tag.TagType, "Entries": entries})
}
p.Data.Value.(map[string]any)["Tags"] = tags
return
}
func handleClient(c *proto.Conn) (err error) {
acc := api.NewOfflineAccount("RegistryHunter")
_, err = server.ServeLogin(c, server.WithOtherAccount(acc), server.WithCompatibleVersions(CompatibleProtocolVersion), server.WithRawStatus(Status))
if err != nil {
return
}
sockPuppet, err := client.Login(":25565", acc)
if err != nil {
return
}
defer sockPuppet.Close()
errChan := make(chan error)
p := &Proxy{Client: sockPuppet, Servee: c}
p.Data.Value = map[string]any{"Registries": []any{}}
p.Client.RegisterCritical(p.OnAnything)
p.Servee.RegisterCritical(p.OnAnything)
p.Client.RegisterCriticalUntilLatest(p.OnData)
p.Client.RegisterCriticalUntilLatest(p.OnTags)
p.Client.RegisterCriticalUntilLatest(p.OnSelectKnownPacks)
p.Client.RegisterCriticalUntilLatest(p.OnFinishConfiguration)
go func() {
errChan <- p.Client.StartConn()
}()
go func() {
errChan <- p.Servee.StartConn()
}()
err = <-errChan
f, err := os.Create(SaveAs)
if err != nil {
return
}
defer f.Close()
err = nbt.WriteUnstructuredFile(f, p.Data)
slog.Info("saved", "file", SaveAs)
return
}
func Run(args []string) error {
slog.SetLogLoggerLevel(slog.LevelDebug)
return server.StartServerWithOnConn(":25566", handleClient)
}
+5 -5
View File
@@ -9,11 +9,11 @@ import (
"os"
"time"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto/replay"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"github.com/admin-else/strom/mc/server"
"git.anygate.cloud/anygatecloud/strom/mc/event"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto/replay"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_8"
"git.anygate.cloud/anygatecloud/strom/mc/server"
)
type Server struct {
+8 -8
View File
@@ -8,14 +8,14 @@ import (
"os"
"time"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/level"
"github.com/admin-else/strom/mc/level/anvil"
"github.com/admin-else/strom/mc/nbt"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"github.com/admin-else/strom/mc/server"
"github.com/admin-else/strom/mc/util"
"git.anygate.cloud/anygatecloud/strom/mc/event"
"git.anygate.cloud/anygatecloud/strom/mc/level"
"git.anygate.cloud/anygatecloud/strom/mc/level/anvil"
"git.anygate.cloud/anygatecloud/strom/mc/nbt"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_8"
"git.anygate.cloud/anygatecloud/strom/mc/server"
"git.anygate.cloud/anygatecloud/strom/mc/util"
)
type Server struct {
+5 -5
View File
@@ -6,11 +6,11 @@ import (
"log/slog"
"time"
"github.com/admin-else/strom/mc/client"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"git.anygate.cloud/anygatecloud/strom/mc/client"
"git.anygate.cloud/anygatecloud/strom/mc/event"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_8"
)
var cmd = flag.NewFlagSet("status", flag.ContinueOnError)
+1 -1
View File
@@ -1,4 +1,4 @@
module github.com/admin-else/strom
module git.anygate.cloud/anygatecloud/strom
go 1.26.2
+5
View File
@@ -289,6 +289,9 @@ func (a *Account) CheckGiftCodeValidity(giftCode string) (valid bool, err error)
return
}
// NewAccountFromYGG creates an Account by authenticating the YGG token against
// Mojang's API. It makes an HTTP call to fetch the player profile and returns
// an Account with name and UUID populated, or an error if authentication fails.
func NewAccountFromYGG(ygg string) (a *Account, err error) {
a = &Account{
Ygg: ygg,
@@ -303,6 +306,8 @@ func NewAccountFromYGG(ygg string) (a *Account, err error) {
return
}
// NewAccount creates an Account from explicit name, UUID, and YGG token without
// making any HTTP calls. The account uses Mojang's default API servers.
func NewAccount(name string, uuid uuid.UUID, ygg string) (a *Account) {
return &Account{
Name: name,
+3 -1
View File
@@ -1,9 +1,11 @@
package api
import (
"github.com/admin-else/strom/mc/crypto"
"git.anygate.cloud/anygatecloud/strom/mc/crypto"
)
// NewOfflineAccount creates an offline-mode Account with a UUID derived from the
// player name. No HTTP calls are made; the UUID is computed locally.
func NewOfflineAccount(name string) *Account {
return &Account{
Name: name,
+13
View File
@@ -9,6 +9,8 @@ import (
"strings"
)
// BlockedServers fetches the list of SHA-1 hashes of blocked server IPs from
// Mojang's session server. The returned strings are hex-encoded hashes.
func BlockedServers() (s []string, err error) {
resp, err := http.Get("https://sessionserver.mojang.com/blockedservers")
if err != nil {
@@ -36,6 +38,9 @@ type ProfileResp struct {
Properties []ProfileProperty `json:"properties"`
}
// HasJoined checks with Mojang's session server whether a player has joined a
// given server. name is the player name, server is the server hash, and ip is
// the optional player IP address. Returns the player's profile on success.
func HasJoined(name, server, ip string) (p ProfileResp, err error) {
url := "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" + name + "&serverId=" + server
if ip != "" {
@@ -62,6 +67,8 @@ type MojangPublicKeysResp struct {
AuthenticationKeys []string `json:"authenticationKeys"`
}
// MojangPublicKeys fetches Mojang's public keys for profile property signing and
// player certificate verification from the session server.
func MojangPublicKeys() (keys MojangPublicKeysResp, err error) {
resp, err := http.Get("https://sessionserver.mojang.com/session/minecraft/profile/public_key_by_token")
if err != nil {
@@ -72,6 +79,8 @@ func MojangPublicKeys() (keys MojangPublicKeysResp, err error) {
return
}
// Profile fetches a player's profile by UUID from Mojang's session server.
// If unsigned is false, signed profile properties are included in the response.
func Profile(id string, unsinged bool) (p ProfileResp, err error) {
url := "https://sessionserver.mojang.com/session/minecraft/profile/" + id
if !unsinged {
@@ -91,6 +100,8 @@ type IdName struct {
Name string `json:"name"`
}
// NameToId resolves a Minecraft player name to a UUID and canonical name by
// making an HTTP GET to Mojang's API.
func NameToId(name string) (idName IdName, err error) {
// may also use these:
//https://api.mojang.com/users/profiles/minecraft/<player name>
@@ -105,6 +116,8 @@ func NameToId(name string) (idName IdName, err error) {
return
}
// NameToIdBulk resolves multiple Minecraft player names to UUIDs and canonical
// names in a single HTTP POST to Mojang's API.
func NameToIdBulk(names []string) (idNames []IdName, err error) {
b := bytes.NewBuffer(nil)
err = json.NewEncoder(b).Encode(names)
+12 -4
View File
@@ -12,9 +12,10 @@ import (
"fmt"
"time"
"github.com/admin-else/strom/mc/api"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_generated/v1_21_11"
"git.anygate.cloud/anygatecloud/strom/mc/api"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_11"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_8"
"github.com/google/uuid"
)
@@ -43,6 +44,9 @@ func Start(c *proto.Conn, acc *api.Account) (*Module, error) {
}
func (m *Module) initSigning(acc *api.Account) (err error) {
if m.Conn.ProtocolVersion < 764 {
return nil
}
keys, err := acc.FetchKeys()
if err != nil {
return fmt.Errorf("fetch profile keys: %w", err)
@@ -80,8 +84,12 @@ func (m *Module) initSigning(acc *api.Account) (err error) {
}
// SendMessage sends a chat message. If signing is enabled, the message is signed;
// otherwise it is sent unsigned.
// otherwise it is sent unsigned. For pre-1.19 protocol versions, uses the legacy
// chat packet format (plain string).
func (m *Module) SendMessage(message string) (err error) {
if m.Conn.ProtocolVersion < 764 {
return m.Conn.Send(&v1_8.PlayToServerPacketChat{Message: message})
}
if m.canSign {
return m.sendSigned(message)
}
+3 -2
View File
@@ -1,8 +1,8 @@
package keepalive
import (
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_8"
)
type mod struct {
@@ -13,6 +13,7 @@ func (m *mod) onKeepAlive(p *v1_21_8.PlayToClientPacketKeepAlive) (err error) {
return m.Send(&v1_21_8.PlayToServerPacketKeepAlive{KeepAliveId: p.KeepAliveId})
}
// Start begins responding to keep-alive packets on the connection.
func Start(c *proto.Conn) {
m := &mod{Conn: c}
m.RegisterUntilLatest(m.onKeepAlive)
+3 -3
View File
@@ -5,9 +5,9 @@ import (
"errors"
"sync"
"github.com/admin-else/strom/mc/level"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_generated/v1_21_11"
"git.anygate.cloud/anygatecloud/strom/mc/level"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_11"
)
var (
+29 -4
View File
@@ -2,12 +2,13 @@ package client
import (
"context"
"errors"
"net"
"github.com/admin-else/strom/mc/data"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/server"
"git.anygate.cloud/anygatecloud/strom/mc/data"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/server"
)
// Connect connects to the given address note that it does not resolve the SRV records it's just a raw net.Dial
@@ -21,6 +22,10 @@ func Connect(ctx context.Context, addr string, version string) (ret *proto.Conn,
if err != nil {
return
}
if s.Version.Protocol == 0 {
err = errors.New("server didnt return protocol version")
return
}
protocolVersion = s.Version.Protocol
} else {
var v data.VersionInfo
@@ -55,3 +60,23 @@ func ConnectVersionLess(ctx context.Context, addr string) (ret *proto.Conn, err
ret.W = ret.Conn
return
}
// ConnectWithConn wraps an existing net.Conn into a proto.Conn with the given
// Minecraft version. The version must be non-empty.
func ConnectWithConn(ctx context.Context, conn net.Conn, version string) (ret *proto.Conn, err error) {
if ctx == nil {
ctx = context.Background()
}
ret = proto.NewConnCtx(ctx)
ret.Actor = proto_base.Client
ret.Conn = conn
ret.R = conn
ret.W = conn
v, err := data.LookUpVersionByName(version)
if err != nil {
return
}
ret.ProtocolVersion = v.Version
ret.Version = version
return
}
+5 -4
View File
@@ -4,10 +4,10 @@ import (
"errors"
"fmt"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"git.anygate.cloud/anygatecloud/strom/mc/event"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_8"
)
type ConfigIgnorer struct {
@@ -47,6 +47,7 @@ func (c *ConfigIgnorer) OnKeepAlive(packet *v1_21_8.ConfigurationToClientPacketK
return
}
// IgnoreConfig acknowledges configuration packets on the connection and transitions it to the Play state once configuration is complete.
func IgnoreConfig(c *proto.Conn) (err error) {
ci := &ConfigIgnorer{c}
ci.RegisterCritical(ci.Default)
+4 -3
View File
@@ -4,11 +4,12 @@ import (
"net"
"strconv"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_8"
)
// MakeHandshakePacket creates a handshake packet using the connection's remote address as the server host.
func MakeHandshakePacket(c *proto.Conn, nextState proto_base.State) (p *v1_21_8.HandshakingToServerPacketSetProtocol, err error) {
return MakeHandshakePacketAddr(c, nextState, c.RemoteAddr().String())
}
+143 -26
View File
@@ -7,15 +7,19 @@ import (
"crypto/x509"
"encoding/json"
"errors"
"net"
"github.com/admin-else/strom/mc/api"
"github.com/admin-else/strom/mc/crypto"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"github.com/admin-else/strom/mc/proto_generated/v26_2"
"github.com/admin-else/strom/mc/text"
"git.anygate.cloud/anygatecloud/strom/mc/api"
"git.anygate.cloud/anygatecloud/strom/mc/crypto"
"git.anygate.cloud/anygatecloud/strom/mc/event"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_16_5"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_8"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_8"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v26_2"
"git.anygate.cloud/anygatecloud/strom/mc/text"
"github.com/google/uuid"
)
type LoginClient struct {
@@ -53,28 +57,36 @@ func (s *LoginClient) OnClose(_ event.Close) (err error) {
return
}
func (s *LoginClient) OnCompress(compress *v1_21_8.LoginToClientPacketCompress) (err error) {
s.SetCompressionThreshold(compress.Threshold)
func (s *LoginClient) OnCompress(packet *v1_8.LoginToClientPacketCompress) (err error) {
s.SetCompressionThreshold(packet.Threshold)
return
}
func (s *LoginClient) OnEncryptV1_8(packet *v1_8.LoginToClientPacketEncryptionBegin) (err error) {
return s.doEncrypt(packet.ServerId, packet.PublicKey, packet.VerifyToken, true)
}
func (s *LoginClient) OnEncrypt(packet *v1_21_8.LoginToClientPacketEncryptionBegin) (err error) {
return s.doEncrypt(packet.ServerId, packet.PublicKey, packet.VerifyToken, packet.ShouldAuthenticate)
}
func (s *LoginClient) doEncrypt(serverId string, publicKey []byte, verifyToken []byte, shouldAuthenticate bool) (err error) {
sharedSecret := make([]byte, 16)
_, _ = rand.Read(sharedSecret) //never fails
if packet.ShouldAuthenticate {
if shouldAuthenticate {
if s.Account.Ygg == "" {
err = NoTokenErr
return
}
serverId := crypto.AuthDigest([]byte(packet.ServerId), sharedSecret, packet.PublicKey)
err = s.Account.JoinServer(serverId)
hash := crypto.AuthDigest([]byte(serverId), sharedSecret, publicKey)
err = s.Account.JoinServer(hash)
if err != nil {
return
}
}
pubAny, err := x509.ParsePKIXPublicKey(packet.PublicKey)
pubAny, err := x509.ParsePKIXPublicKey(publicKey)
if err != nil {
return
}
@@ -83,7 +95,7 @@ func (s *LoginClient) OnEncrypt(packet *v1_21_8.LoginToClientPacketEncryptionBeg
err = BadPublicKeyTypeErr
return
}
verifyTokenEnc, err := rsa.EncryptPKCS1v15(rand.Reader, pub, packet.VerifyToken)
verifyTokenEnc, err := rsa.EncryptPKCS1v15(rand.Reader, pub, verifyToken)
if err != nil {
return
}
@@ -98,10 +110,9 @@ func (s *LoginClient) OnEncrypt(packet *v1_21_8.LoginToClientPacketEncryptionBeg
}
err = s.SetSecret(sharedSecret)
return
}
func (s *LoginClient) OnDisconnect(packet *v1_21_8.LoginToClientPacketDisconnect) (err error) {
func (s *LoginClient) OnDisconnect(packet *v1_8.LoginToClientPacketDisconnect) (err error) {
var reason text.Component
err = json.Unmarshal([]byte(packet.Reason), &reason)
if err != nil {
@@ -111,13 +122,27 @@ func (s *LoginClient) OnDisconnect(packet *v1_21_8.LoginToClientPacketDisconnect
return
}
func (s *LoginClient) OnSuccessV1_8(success *v1_8.LoginToClientPacketSuccess) (err error) {
s.GivenAccount = &v1_21_8.LoginToClientPacketSuccess{
Uuid: uuid.MustParse(success.Uuid),
Username: success.Username,
}
s.SetState(proto_base.Play)
err = event.HandlerDoneErr{}
return
}
func (s *LoginClient) OnSuccess(success *v1_21_8.LoginToClientPacketSuccess) (err error) {
s.GivenAccount = success
if s.ProtocolVersion >= 764 {
err = s.Send(&v1_21_8.LoginToServerPacketLoginAcknowledged{})
if err != nil {
return
}
s.SetState(proto_base.Configuration)
} else {
s.SetState(proto_base.Play)
}
err = event.HandlerDoneErr{}
return
}
@@ -130,24 +155,44 @@ func (s *LoginClient) OnSuccess26_2(success *v26_2.LoginToClientPacketSuccess) (
})
}
func (s *LoginClient) OnSuccess1_16_5(success *v1_16_5.LoginToClientPacketSuccess) (err error) {
return s.OnSuccess(&v1_21_8.LoginToClientPacketSuccess{
Uuid: success.Uuid,
Username: success.Username,
})
}
func (s *LoginClient) OnStart() (err error) {
return
}
// LoginRaw performs the login handshake on an already-established connection without DNS resolution or configuration handling.
// The handshake address is derived from the connection's RemoteAddr.
func LoginRaw(c *proto.Conn, account *api.Account) (err error) {
return LoginRawAddr(c, account, "")
}
// LoginRawAddr performs the login handshake on an already-established connection using the given address for the handshake packet.
// If hostAddr is empty, the handshake address is derived from the connection's RemoteAddr.
func LoginRawAddr(c *proto.Conn, account *api.Account, hostAddr string) (err error) {
lc := &LoginClient{
Conn: c,
Account: account,
}
lc.RegisterCritical(lc.OnDefault)
lc.RegisterCritical(lc.OnClose)
lc.RegisterCriticalUntilLatest(lc.OnCompress)
lc.RegisterCriticalUntilLatest(lc.OnEncrypt)
lc.RegisterCriticalUntilLatest(lc.OnDisconnect)
lc.RegisterCriticalUntil("26.1", lc.OnSuccess)
lc.RegisterCriticalUntilLatest(lc.OnSuccess26_2)
lc.RegisterUntil("26.2", lc.OnCompress, lc.OnDisconnect, lc.OnEncrypt)
lc.RegisterUntil("26.1", lc.OnSuccess)
lc.RegisterUntilLatest(lc.OnSuccess26_2)
lc.RegisterUntil("1.14.4", lc.OnEncryptV1_8, lc.OnSuccessV1_8)
lc.RegisterUntil("1.16.5", lc.OnSuccess1_16_5)
p, err := MakeHandshakePacket(lc.Conn, proto_base.Login)
var p proto_base.EncodeDecodeAble
if hostAddr != "" {
p, err = MakeHandshakePacketAddr(lc.Conn, proto_base.Login, hostAddr)
} else {
p, err = MakeHandshakePacket(lc.Conn, proto_base.Login)
}
if err != nil {
return
}
@@ -157,7 +202,11 @@ func LoginRaw(c *proto.Conn, account *api.Account) (err error) {
return
}
lc.SetState(proto_base.Login)
if lc.Conn.ProtocolVersion < 759 {
err = lc.Send(&v1_8.LoginToServerPacketLoginStart{Username: lc.Account.Name})
} else {
err = lc.Send(&v1_21_8.LoginToServerPacketLoginStart{Username: lc.Account.Name, PlayerUUID: lc.Account.Uuid})
}
err = lc.StartConn()
if err != nil {
@@ -166,31 +215,67 @@ func LoginRaw(c *proto.Conn, account *api.Account) (err error) {
return
}
// WithoutDns returns a login setting that disables SRV DNS resolution during login.
func WithoutDns() func(ls *loginSettings) {
return func(ls *loginSettings) {
ls.NoDns = true
}
}
// WithContext returns a login setting that sets the context used for the connection dial and DNS resolution.
func WithContext(ctx context.Context) func(ls *loginSettings) {
return func(ls *loginSettings) {
ls.Ctx = ctx
}
}
// WithVersion returns a login setting that forces a specific Minecraft version string for the connection.
func WithVersion(version string) func(ls *loginSettings) {
return func(ls *loginSettings) {
ls.Version = version
}
}
func WithIgnoreConfig() func(ls *loginSettings) {
return func(ls *loginSettings) {
ls.IgnoreConfig = true
}
}
// DialFunc is a context-aware dial function used by Login to establish a TCP connection.
type DialFunc func(ctx context.Context, network, addr string) (net.Conn, error)
// WithConn returns a login setting that uses an already-established net.Conn instead of dialling.
// WithVersion must also be set; auto-detection is not possible with a pre-established connection.
func WithConn(conn net.Conn) func(ls *loginSettings) {
return func(ls *loginSettings) {
ls.Conn = conn
}
}
// WithDialer returns a login setting that uses the given dial function instead of net.Dialer.
// Auto version detection via status ping is still supported when no explicit version is set.
func WithDialer(d DialFunc) func(ls *loginSettings) {
return func(ls *loginSettings) {
ls.Dialer = d
}
}
var (
ErrWithConnRequiresVersion = errors.New("WithVersion is required when using WithConn")
ErrWithConnNoStatus = errors.New("auto version detection is not supported with WithConn")
)
type loginSettings struct {
NoDns bool
Ctx context.Context
Version string
IgnoreConfig bool
Conn net.Conn
Dialer DialFunc
}
// Login resolves the address with SRV DNS, connects, performs the login handshake, and handles the configuration phase, returning an authenticated connection ready for play.
func Login(connectTo string, account *api.Account, settings ...func(ls *loginSettings)) (c *proto.Conn, err error) {
ls := &loginSettings{}
@@ -198,22 +283,54 @@ func Login(connectTo string, account *api.Account, settings ...func(ls *loginSet
setting(ls)
}
hostAddr := connectTo
if ls.Conn != nil {
if ls.Version == "" {
return nil, ErrWithConnRequiresVersion
}
c, err = ConnectWithConn(ls.Ctx, ls.Conn, ls.Version)
if err != nil {
return
}
} else if ls.Dialer != nil {
if ls.Version == "" {
return nil, ErrWithConnRequiresVersion
}
if !ls.NoDns {
connectTo, _, _, err = DoDNSChecked(ls.Ctx, connectTo, nil)
if err != nil {
return
}
}
var conn net.Conn
conn, err = ls.Dialer(ls.Ctx, "tcp", connectTo)
if err != nil {
return
}
c, err = ConnectWithConn(ls.Ctx, conn, ls.Version)
if err != nil {
conn.Close()
return
}
} else {
if !ls.NoDns {
connectTo, _, _, err = DoDNSChecked(ls.Ctx, connectTo, nil)
if err != nil {
return
}
}
c, err = Connect(ls.Ctx, connectTo, ls.Version)
if err != nil {
return
}
err = LoginRaw(c, account)
}
err = LoginRawAddr(c, account, hostAddr)
if err != nil {
return
}
if !ls.IgnoreConfig {
if !ls.IgnoreConfig && c.ProtocolVersion >= 764 {
err = IgnoreConfig(c)
}
return
+4 -4
View File
@@ -4,10 +4,10 @@ import (
"reflect"
"testing"
"github.com/admin-else/strom/mc/data"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"git.anygate.cloud/anygatecloud/strom/mc/data"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_8"
)
func assertClientSendConvertible(t *testing.T, srcType reflect.Type, name string, state proto_base.State, direction proto_base.Direction, targetVersion int32) {
+19 -13
View File
@@ -5,11 +5,12 @@ import (
"encoding/json"
"time"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"github.com/admin-else/strom/mc/server"
"git.anygate.cloud/anygatecloud/strom/mc/event"
"git.anygate.cloud/anygatecloud/strom/mc/proto"
"git.anygate.cloud/anygatecloud/strom/mc/proto_base"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_21_8"
"git.anygate.cloud/anygatecloud/strom/mc/proto_generated/v1_8"
"git.anygate.cloud/anygatecloud/strom/mc/server"
)
type StatusClient struct {
@@ -19,7 +20,7 @@ type StatusClient struct {
DoPingRoundTripTime bool
}
func (s *StatusClient) OnStatus(p *v1_21_8.StatusToClientPacketServerInfo) (err error) {
func (s *StatusClient) OnStatus(p *v1_8.StatusToClientPacketServerInfo) (err error) {
s.Status = p.Response
s.PingSendTime = time.Now()
if s.DoPingRoundTripTime {
@@ -30,7 +31,7 @@ func (s *StatusClient) OnStatus(p *v1_21_8.StatusToClientPacketServerInfo) (err
return
}
func (s *StatusClient) OnPong(p *v1_21_8.StatusToClientPacketPing) (err error) {
func (s *StatusClient) OnPong(p *v1_8.StatusToClientPacketPing) (err error) {
s.PingReceiveTime = time.Now()
err = event.HandlerDoneErr{}
return
@@ -40,20 +41,24 @@ func (s *StatusClient) OnPong(p *v1_21_8.StatusToClientPacketPing) (err error) {
// So ignore the resource leak warning. And maybe attach a warn ignore comment.
// It does not resolve SRV records.
func StatusRaw(ctx context.Context, addr string) (s *StatusClient, err error) {
return StatusRawWithVersion(ctx, addr, "1.21.8")
}
// StatusRawWithVersion is like StatusRaw but uses the given Minecraft version for the handshake.
func StatusRawWithVersion(ctx context.Context, addr, version string) (s *StatusClient, err error) {
c, err := ConnectVersionLess(ctx, addr)
if err != nil {
return
}
defer c.Close()
err = c.SetVersion("1.21.8")
err = c.SetVersion(version)
if err != nil {
return
}
s = &StatusClient{
Conn: c,
}
s.RegisterCriticalUntilLatest(s.OnStatus)
s.RegisterCriticalUntilLatest(s.OnPong)
s.RegisterUntil("26.2", s.OnStatus, s.OnPong)
p, err := MakeHandshakePacketAddr(s.Conn, proto_base.Status, addr)
if err != nil {
@@ -71,11 +76,12 @@ func StatusRaw(ctx context.Context, addr string) (s *StatusClient, err error) {
}
// StatusNoDns is like Status but does not resolve SRV records.
func StatusNoDns(addr string) (status server.StatusResponse, err error) {
s, err := StatusRaw(context.Background(), addr)
func StatusNoDns(ctx context.Context, addr string) (status server.StatusResponse, err error) {
s, err := StatusRaw(ctx, addr)
if err != nil {
return
}
defer s.Close()
err = json.Unmarshal([]byte(s.Status), &status)
return
}
@@ -86,5 +92,5 @@ func Status(ctx context.Context, addr string) (status server.StatusResponse, err
if err != nil {
return
}
return StatusNoDns(addr)
return StatusNoDns(ctx, addr)
}
+2
View File
@@ -41,10 +41,12 @@ type CFB8 struct {
mutex sync.Mutex
}
// NewCFB8Decrypt creates a new CFB8 stream cipher in decrypt mode.
func NewCFB8Decrypt(c cipher.Block, iv []byte) *CFB8 {
return newCFB8(c, iv, true)
}
// NewCFB8Encrypt creates a new CFB8 stream cipher in encrypt mode.
func NewCFB8Encrypt(c cipher.Block, iv []byte) *CFB8 {
return newCFB8(c, iv, false)
}
+1
View File
@@ -21,6 +21,7 @@ func uuidV3(space []byte, data []byte) uuid.UUID {
return u
}
// FromOfflinePlayer generates a UUID for an offline-mode (cracked) player from their display name.
func FromOfflinePlayer(displayName string) uuid.UUID {
return uuidV3([]byte("OfflinePlayer:"), []byte(displayName))
}
+3
View File
@@ -28,6 +28,7 @@ type Biome struct {
var BiomesCache = make(map[string][]*Biome)
// BiomesForVersion returns the biome definitions for the given Minecraft version, caching them after the first load.
func BiomesForVersion(v string) (ret []*Biome) {
var ok bool
if ret, ok = BiomesCache[v]; ok {
@@ -39,6 +40,7 @@ func BiomesForVersion(v string) (ret []*Biome) {
return b
}
// LookupBiomeById returns the biome with the given numeric ID in the given version.
func LookupBiomeById(version string, id int32) (biome *Biome, ok bool) {
for _, b := range BiomesForVersion(version) {
if b.Id == id {
@@ -52,6 +54,7 @@ func LookupBiomeById(version string, id int32) (biome *Biome, ok bool) {
var UnknownBiomeNameErr = errors.New("unknown biome Name")
// LookupBiomeByName returns the biome with the given name in the given version.
func LookupBiomeByName(version string, name string) (biome *Biome, ok bool) {
for _, b := range BiomesForVersion(version) {
if b.Name == name {
+1 -1
View File
@@ -3,7 +3,7 @@ package data_test
import (
"testing"
"github.com/admin-else/strom/mc/data"
"git.anygate.cloud/anygatecloud/strom/mc/data"
)
func TestLookupBiomeById(t *testing.T) {
+6 -1
View File
@@ -5,7 +5,7 @@ import (
"slices"
"strconv"
"github.com/admin-else/strom/mc/util"
"git.anygate.cloud/anygatecloud/strom/mc/util"
)
// {
@@ -59,6 +59,7 @@ type BlockState struct {
var BlocksCache = make(map[string][]*Block)
var BlocksCacheIdMap = make(map[string]map[int32]*Block)
// BlocksForVersion returns the block definitions for the given Minecraft version, caching them after the first load.
func BlocksForVersion(v string) (ret []*Block) {
var ok bool
if ret, ok = BlocksCache[v]; ok {
@@ -84,6 +85,7 @@ func BlocksForVersion(v string) (ret []*Block) {
return b
}
// LookupBlockByStateId returns the block for the given global palette state ID in the given version.
func LookupBlockByStateId(version string, stateId int32) (block *Block, ok bool) {
idmap, found := BlocksCacheIdMap[version]
if !found {
@@ -101,6 +103,7 @@ func LookupBlockByStateId(version string, stateId int32) (block *Block, ok bool)
var UnknownBlockNameErr = errors.New("unknown block Name")
// LookupBlockByName returns the block with the given name in the given version.
func LookupBlockByName(version string, name string) (block *Block, ok bool) {
for _, b := range BlocksForVersion(version) {
if b.Name == name {
@@ -111,6 +114,7 @@ func LookupBlockByName(version string, name string) (block *Block, ok bool) {
return
}
// StateIdFromBlocKAndStateMap returns the global palette state ID for the given block name and state property map in the given version.
func StateIdFromBlocKAndStateMap(version string, name string, stateMap map[string]string) (stateId int32, err error) {
b, ok := LookupBlockByName(version, name)
if !ok {
@@ -135,6 +139,7 @@ var BadBlockStateTypeErr = errors.New("bad block state type")
var BadEnumErr = errors.New("bad enum")
var SupplyAllStatesErr = errors.New("supply all states")
// FromBlockState converts a global palette state ID back into a block definition and a map of state properties.
func FromBlockState(version string, stateId int32) (b *Block, stateData map[string]string, err error) {
b, ok := LookupBlockByStateId(version, stateId)
if !ok {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"testing"
"github.com/admin-else/strom/mc/data"
"git.anygate.cloud/anygatecloud/strom/mc/data"
)
func TestLookupBlockByStateId(t *testing.T) {
+2
View File
@@ -12,6 +12,7 @@ import (
//go:embed minecraft-data/pc minecraft-data/dataPaths.json
var MinecraftData embed.FS
// LoadJson reads a JSON file from the embedded minecraft-data FS and unmarshals it into data.
func LoadJson(path string, data any) (err error) {
b, err := MinecraftData.ReadFile(path)
if err != nil {
@@ -21,6 +22,7 @@ func LoadJson(path string, data any) (err error) {
return
}
// LoadVersionedJson loads a version-specific JSON data file from the embedded minecraft-data FS and unmarshals it into data.
func LoadVersionedJson(version, dataName string, data any) (err error) {
b, err := MinecraftData.ReadFile("minecraft-data/" + Paths.Data[version][dataName] + "/" + dataName + ".json")
if err != nil {
+10 -1
View File
@@ -6,7 +6,7 @@ set -xeuo pipefail
cd "$(dirname "$0")"
rm -rf minecraft-data/
git clone --depth 1 git@github.com:PrismarineJS/minecraft-data.git
git clone --depth 1 git@github.com:admin-else/minecraft-data.git
mv minecraft-data minecraft-data-untrimmed
mkdir minecraft-data
@@ -20,8 +20,17 @@ copy-mc() {
copy-mc common
# Legacy versions
copy-mc 1.8
copy-mc 1.12.2
copy-mc 1.14.4
copy-mc 1.16.5
# Modern versions
copy-mc 1.21.8
copy-mc 1.21.9
copy-mc 1.21.11
copy-mc 26.1
copy-mc 26.2
rm -rf minecraft-data-untrimmed
+3
View File
@@ -19,6 +19,7 @@ type Item struct {
var ItemsCache = make(map[string][]*Item)
var ItemsCacheMutex = &sync.RWMutex{}
// ItemsForVersion returns the item definitions for the given Minecraft version, caching them after the first load.
func ItemsForVersion(v string) (ret []*Item) {
var ok bool
ItemsCacheMutex.RLock()
@@ -35,6 +36,7 @@ func ItemsForVersion(v string) (ret []*Item) {
return b
}
// LookupItemById returns the item with the given numeric ID in the given version.
func LookupItemById(version string, id int32) (item *Item, ok bool) {
for _, i := range ItemsForVersion(version) {
if i.Id == id {
@@ -46,6 +48,7 @@ func LookupItemById(version string, id int32) (item *Item, ok bool) {
return
}
// LookupItemByName returns the item with the given name in the given version.
func LookupItemByName(version string, name string) (item *Item, ok bool) {
for _, i := range ItemsForVersion(version) {
if i.Name == name {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,5 @@
{
"minecraftVersion": "1.12.2",
"version":340,
"majorVersion": "1.12"
}
@@ -0,0 +1,953 @@
[
{
"id": 0,
"name": "ocean",
"category": "ocean",
"temperature": 0.5,
"precipitation": "rain",
"depth": -1,
"dimension": "overworld",
"displayName": "Ocean",
"color": 112,
"rainfall": 0.5
},
{
"id": 1,
"name": "plains",
"category": "plains",
"temperature": 0.8,
"precipitation": "rain",
"depth": 0.125,
"dimension": "overworld",
"displayName": "Plains",
"color": 9286496,
"rainfall": 0.4,
"child": 129
},
{
"id": 2,
"name": "desert",
"category": "desert",
"temperature": 2,
"precipitation": "none",
"depth": 0.125,
"dimension": "overworld",
"displayName": "Desert",
"color": 16421912,
"rainfall": 0,
"child": 130
},
{
"id": 3,
"name": "mountains",
"category": "extreme_hills",
"temperature": 0.2,
"precipitation": "rain",
"depth": 1,
"dimension": "overworld",
"displayName": "Mountains",
"color": 6316128,
"rainfall": 0.3,
"child": 131
},
{
"id": 4,
"name": "forest",
"category": "forest",
"temperature": 0.7,
"precipitation": "rain",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Forest",
"color": 353825,
"rainfall": 0.8,
"child": 132
},
{
"id": 5,
"name": "taiga",
"category": "taiga",
"temperature": 0.25,
"precipitation": "rain",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Taiga",
"color": 747097,
"rainfall": 0.8,
"child": 133
},
{
"id": 6,
"name": "swamp",
"category": "swamp",
"temperature": 0.8,
"precipitation": "rain",
"depth": -0.2,
"dimension": "overworld",
"displayName": "Swamp",
"color": 522674,
"rainfall": 0.9,
"child": 134
},
{
"id": 7,
"name": "river",
"category": "river",
"temperature": 0.5,
"precipitation": "rain",
"depth": -0.5,
"dimension": "overworld",
"displayName": "River",
"color": 255,
"rainfall": 0.5
},
{
"id": 8,
"name": "nether_wastes",
"category": "nether",
"temperature": 2,
"precipitation": "none",
"depth": 0.1,
"climates": [
{
"temperature": 0,
"humidity": 0,
"altitude": 0,
"weirdness": 0,
"offset": 0
}
],
"dimension": "nether",
"displayName": "Nether Wastes",
"color": 12532539,
"rainfall": 0
},
{
"id": 9,
"name": "the_end",
"category": "the_end",
"temperature": 0.5,
"precipitation": "none",
"depth": 0.1,
"dimension": "end",
"displayName": "The End",
"color": 8421631,
"rainfall": 0.5
},
{
"id": 10,
"name": "frozen_ocean",
"category": "ocean",
"temperature": 0,
"precipitation": "snow",
"depth": -1,
"dimension": "overworld",
"displayName": "Frozen Ocean",
"color": 7368918,
"rainfall": 0.5
},
{
"id": 11,
"name": "frozen_river",
"category": "river",
"temperature": 0,
"precipitation": "snow",
"depth": -0.5,
"dimension": "overworld",
"displayName": "Frozen River",
"color": 10526975,
"rainfall": 0.5
},
{
"id": 12,
"name": "snowy_tundra",
"category": "icy",
"temperature": 0,
"precipitation": "snow",
"depth": 0.125,
"dimension": "overworld",
"displayName": "Snowy Tundra",
"color": 16777215,
"rainfall": 0.5,
"child": 140
},
{
"id": 13,
"name": "snowy_mountains",
"category": "icy",
"temperature": 0,
"precipitation": "snow",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Snowy Mountains",
"color": 10526880,
"rainfall": 0.5
},
{
"id": 14,
"name": "mushroom_fields",
"category": "mushroom",
"temperature": 0.9,
"precipitation": "rain",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Mushroom Fields",
"color": 16711935,
"rainfall": 1
},
{
"id": 15,
"name": "mushroom_field_shore",
"category": "mushroom",
"temperature": 0.9,
"precipitation": "rain",
"depth": 0,
"dimension": "overworld",
"displayName": "Mushroom Fields Shore",
"color": 10486015,
"rainfall": 1
},
{
"id": 16,
"name": "beach",
"category": "beach",
"temperature": 0.8,
"precipitation": "rain",
"depth": 0,
"dimension": "overworld",
"displayName": "Beach",
"color": 16440917,
"rainfall": 0.4
},
{
"id": 17,
"name": "desert_hills",
"category": "desert",
"temperature": 2,
"precipitation": "none",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Desert Hills",
"color": 13786898,
"rainfall": 0
},
{
"id": 18,
"name": "wooded_hills",
"category": "forest",
"temperature": 0.7,
"precipitation": "rain",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Wooded Hills",
"color": 2250012,
"rainfall": 0.8
},
{
"id": 19,
"name": "taiga_hills",
"category": "taiga",
"temperature": 0.25,
"precipitation": "rain",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Taiga Hills",
"color": 1456435,
"rainfall": 0.8
},
{
"id": 20,
"name": "mountain_edge",
"category": "extreme_hills",
"temperature": 0.2,
"precipitation": "rain",
"depth": 0.8,
"dimension": "overworld",
"displayName": "Mountain Edge",
"color": 7501978,
"rainfall": 0.3
},
{
"id": 21,
"name": "jungle",
"category": "jungle",
"temperature": 0.95,
"precipitation": "rain",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Jungle",
"color": 5470985,
"rainfall": 0.9,
"child": 149
},
{
"id": 22,
"name": "jungle_hills",
"category": "jungle",
"temperature": 0.95,
"precipitation": "rain",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Jungle Hills",
"color": 2900485,
"rainfall": 0.9
},
{
"id": 23,
"name": "jungle_edge",
"category": "jungle",
"temperature": 0.95,
"precipitation": "rain",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Jungle Edge",
"color": 6458135,
"rainfall": 0.8,
"child": 151
},
{
"id": 24,
"name": "deep_ocean",
"category": "ocean",
"temperature": 0.5,
"precipitation": "rain",
"depth": -1.8,
"dimension": "overworld",
"displayName": "Deep Ocean",
"color": 48,
"rainfall": 0.5
},
{
"id": 25,
"name": "stone_shore",
"category": "none",
"temperature": 0.2,
"precipitation": "rain",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Stone Shore",
"color": 10658436,
"rainfall": 0.3
},
{
"id": 26,
"name": "snowy_beach",
"category": "beach",
"temperature": 0.05,
"precipitation": "snow",
"depth": 0,
"dimension": "overworld",
"displayName": "Snowy Beach",
"color": 16445632,
"rainfall": 0.3
},
{
"id": 27,
"name": "birch_forest",
"category": "forest",
"temperature": 0.6,
"precipitation": "rain",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Birch Forest",
"color": 3175492,
"rainfall": 0.6,
"child": 155
},
{
"id": 28,
"name": "birch_forest_hills",
"category": "forest",
"temperature": 0.6,
"precipitation": "rain",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Birch Forest Hills",
"color": 2055986,
"rainfall": 0.6,
"child": 156
},
{
"id": 29,
"name": "dark_forest",
"category": "forest",
"temperature": 0.7,
"precipitation": "rain",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Dark Forest",
"color": 4215066,
"rainfall": 0.8,
"child": 157
},
{
"id": 30,
"name": "snowy_taiga",
"category": "taiga",
"temperature": -0.5,
"precipitation": "snow",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Snowy Taiga",
"color": 3233098,
"rainfall": 0.4,
"child": 158
},
{
"id": 31,
"name": "snowy_taiga_hills",
"category": "taiga",
"temperature": -0.5,
"precipitation": "snow",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Snowy Taiga Hills",
"color": 2375478,
"rainfall": 0.4
},
{
"id": 32,
"name": "giant_tree_taiga",
"category": "taiga",
"temperature": 0.3,
"precipitation": "rain",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Giant Tree Taiga",
"color": 5858897,
"rainfall": 0.8,
"child": 160
},
{
"id": 33,
"name": "giant_tree_taiga_hills",
"category": "taiga",
"temperature": 0.3,
"precipitation": "rain",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Giant Tree Taiga Hills",
"color": 4542270,
"rainfall": 0.8,
"child": 161
},
{
"id": 34,
"name": "wooded_mountains",
"category": "extreme_hills",
"temperature": 0.2,
"precipitation": "rain",
"depth": 1,
"dimension": "overworld",
"displayName": "Wooded Mountains",
"color": 5271632,
"rainfall": 0.3,
"child": 162
},
{
"id": 35,
"name": "savanna",
"category": "savanna",
"temperature": 1.2,
"precipitation": "none",
"depth": 0.125,
"dimension": "overworld",
"displayName": "Savanna",
"color": 12431967,
"rainfall": 0,
"child": 163
},
{
"id": 36,
"name": "savanna_plateau",
"category": "savanna",
"temperature": 1,
"precipitation": "none",
"depth": 1.5,
"dimension": "overworld",
"displayName": "Savanna Plateau",
"color": 10984804,
"rainfall": 0,
"child": 164
},
{
"id": 37,
"name": "badlands",
"category": "mesa",
"temperature": 2,
"precipitation": "none",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Badlands",
"color": 14238997,
"rainfall": 0,
"child": 165
},
{
"id": 38,
"name": "wooded_badlands_plateau",
"category": "mesa",
"temperature": 2,
"precipitation": "none",
"depth": 1.5,
"dimension": "overworld",
"displayName": "Wooded Badlands Plateau",
"color": 11573093,
"rainfall": 0,
"child": 166
},
{
"id": 39,
"name": "badlands_plateau",
"category": "mesa",
"temperature": 2,
"precipitation": "none",
"depth": 1.5,
"dimension": "overworld",
"displayName": "Badlands Plateau",
"color": 13274213,
"rainfall": 0,
"child": 167
},
{
"id": 40,
"name": "small_end_islands",
"category": "the_end",
"temperature": 0.5,
"precipitation": "none",
"depth": 0.1,
"dimension": "end",
"displayName": "Small End Islands",
"color": 42,
"rainfall": 0.5
},
{
"id": 41,
"name": "end_midlands",
"category": "the_end",
"temperature": 0.5,
"precipitation": "none",
"depth": 0.1,
"dimension": "end",
"displayName": "End Midlands",
"color": 15464630,
"rainfall": 0.5
},
{
"id": 42,
"name": "end_highlands",
"category": "the_end",
"temperature": 0.5,
"precipitation": "none",
"depth": 0.1,
"dimension": "end",
"displayName": "End Highlands",
"color": 12828041,
"rainfall": 0.5
},
{
"id": 43,
"name": "end_barrens",
"category": "the_end",
"temperature": 0.5,
"precipitation": "none",
"depth": 0.1,
"dimension": "end",
"displayName": "End Barrens",
"color": 9474162,
"rainfall": 0.5
},
{
"id": 44,
"name": "warm_ocean",
"category": "ocean",
"temperature": 0.5,
"precipitation": "rain",
"depth": -1,
"dimension": "overworld",
"displayName": "Warm Ocean",
"color": 172,
"rainfall": 0.5
},
{
"id": 45,
"name": "lukewarm_ocean",
"category": "ocean",
"temperature": 0.5,
"precipitation": "rain",
"depth": -1,
"dimension": "overworld",
"displayName": "Lukewarm Ocean",
"color": 144,
"rainfall": 0.5
},
{
"id": 46,
"name": "cold_ocean",
"category": "ocean",
"temperature": 0.5,
"precipitation": "rain",
"depth": -1,
"dimension": "overworld",
"displayName": "Cold Ocean",
"color": 2105456,
"rainfall": 0.5
},
{
"id": 47,
"name": "deep_warm_ocean",
"category": "ocean",
"temperature": 0.5,
"precipitation": "rain",
"depth": -1.8,
"dimension": "overworld",
"displayName": "Deep Warm Ocean",
"color": 80,
"rainfall": 0.5
},
{
"id": 48,
"name": "deep_lukewarm_ocean",
"category": "ocean",
"temperature": 0.5,
"precipitation": "rain",
"depth": -1.8,
"dimension": "overworld",
"displayName": "Deep Lukewarm Ocean",
"color": 64,
"rainfall": 0.5
},
{
"id": 49,
"name": "deep_cold_ocean",
"category": "ocean",
"temperature": 0.5,
"precipitation": "rain",
"depth": -1.8,
"dimension": "overworld",
"displayName": "Deep Cold Ocean",
"color": 2105400,
"rainfall": 0.5
},
{
"id": 50,
"name": "deep_frozen_ocean",
"category": "ocean",
"temperature": 0.5,
"precipitation": "rain",
"depth": -1.8,
"dimension": "overworld",
"displayName": "Deep Frozen Ocean",
"color": 4210832,
"rainfall": 0.5
},
{
"id": 127,
"name": "the_void",
"category": "none",
"temperature": 0.5,
"precipitation": "none",
"depth": 0.1,
"dimension": "end",
"displayName": "the_void",
"rainfall": 0.5,
"color": 0
},
{
"id": 129,
"name": "sunflower_plains",
"category": "plains",
"temperature": 0.8,
"precipitation": "rain",
"depth": 0.125,
"dimension": "overworld",
"displayName": "Sunflower Plains",
"color": 11918216,
"parent": "plains",
"rainfall": 0.4
},
{
"id": 130,
"name": "desert_lakes",
"category": "desert",
"temperature": 2,
"precipitation": "none",
"depth": 0.125,
"dimension": "overworld",
"displayName": "Desert Lakes",
"color": 16759872,
"parent": "desert",
"rainfall": 0
},
{
"id": 131,
"name": "gravelly_mountains",
"category": "extreme_hills",
"temperature": 0.2,
"precipitation": "rain",
"depth": 1,
"dimension": "overworld",
"displayName": "Gravelly Mountains",
"color": 8947848,
"parent": "mountains",
"rainfall": 0.3
},
{
"id": 132,
"name": "flower_forest",
"category": "forest",
"temperature": 0.7,
"precipitation": "rain",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Flower Forest",
"color": 2985545,
"parent": "forest",
"rainfall": 0.8
},
{
"id": 133,
"name": "taiga_mountains",
"category": "taiga",
"temperature": 0.25,
"precipitation": "rain",
"depth": 0.3,
"dimension": "overworld",
"displayName": "Taiga Mountains",
"color": 3378817,
"parent": "taiga",
"rainfall": 0.8
},
{
"id": 134,
"name": "swamp_hills",
"category": "swamp",
"temperature": 0.8,
"precipitation": "rain",
"depth": -0.1,
"dimension": "overworld",
"displayName": "Swamp Hills",
"color": 3145690,
"parent": "swamp",
"rainfall": 0.9
},
{
"id": 140,
"name": "ice_spikes",
"category": "icy",
"temperature": 0,
"precipitation": "snow",
"depth": 0.425,
"dimension": "overworld",
"displayName": "Ice Spikes",
"color": 11853020,
"parent": "snowy_tundra",
"rainfall": 0.5
},
{
"id": 149,
"name": "modified_jungle",
"category": "jungle",
"temperature": 0.95,
"precipitation": "rain",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Modified Jungle",
"color": 8102705,
"parent": "jungle",
"rainfall": 0.9
},
{
"id": 151,
"name": "modified_jungle_edge",
"category": "jungle",
"temperature": 0.95,
"precipitation": "rain",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Modified Jungle Edge",
"color": 9089855,
"parent": "jungle_edge",
"rainfall": 0.8
},
{
"id": 155,
"name": "tall_birch_forest",
"category": "forest",
"temperature": 0.6,
"precipitation": "rain",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Tall Birch Forest",
"color": 5807212,
"parent": "birch_forest",
"rainfall": 0.6
},
{
"id": 156,
"name": "tall_birch_hills",
"category": "forest",
"temperature": 0.6,
"precipitation": "rain",
"depth": 0.55,
"dimension": "overworld",
"displayName": "Tall Birch Hills",
"color": 4687706,
"parent": "birch_forest_hills",
"rainfall": 0.6
},
{
"id": 157,
"name": "dark_forest_hills",
"category": "forest",
"temperature": 0.7,
"precipitation": "rain",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Dark Forest Hills",
"color": 6846786,
"parent": "dark_forest",
"rainfall": 0.8
},
{
"id": 158,
"name": "snowy_taiga_mountains",
"category": "taiga",
"temperature": -0.5,
"precipitation": "snow",
"depth": 0.3,
"dimension": "overworld",
"displayName": "Snowy Taiga Mountains",
"color": 5864818,
"parent": "snowy_taiga",
"rainfall": 0.4
},
{
"id": 160,
"name": "giant_spruce_taiga",
"category": "taiga",
"temperature": 0.25,
"precipitation": "rain",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Giant Spruce Taiga",
"color": 8490617,
"parent": "giant_tree_taiga",
"rainfall": 0.8
},
{
"id": 161,
"name": "giant_spruce_taiga_hills",
"category": "taiga",
"temperature": 0.25,
"precipitation": "rain",
"depth": 0.2,
"dimension": "overworld",
"displayName": "Giant Spruce Taiga Hills",
"color": 7173990,
"parent": "giant_tree_taiga_hills",
"rainfall": 0.8
},
{
"id": 162,
"name": "modified_gravelly_mountains",
"category": "extreme_hills",
"temperature": 0.2,
"precipitation": "rain",
"depth": 1,
"dimension": "overworld",
"displayName": "Gravelly Mountains+",
"color": 7903352,
"parent": "wooded_mountains",
"rainfall": 0.3
},
{
"id": 163,
"name": "shattered_savanna",
"category": "savanna",
"temperature": 1.1,
"precipitation": "none",
"depth": 0.3625,
"dimension": "overworld",
"displayName": "Shattered Savanna",
"color": 15063687,
"parent": "savanna",
"rainfall": 0
},
{
"id": 164,
"name": "shattered_savanna_plateau",
"category": "savanna",
"temperature": 1,
"precipitation": "none",
"depth": 1.05,
"dimension": "overworld",
"displayName": "Shattered Savanna Plateau",
"color": 13616524,
"parent": "savanna_plateau",
"rainfall": 0
},
{
"id": 165,
"name": "eroded_badlands",
"category": "mesa",
"temperature": 2,
"precipitation": "none",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Eroded Badlands",
"color": 16739645,
"parent": "badlands",
"rainfall": 0
},
{
"id": 166,
"name": "modified_wooded_badlands_plateau",
"category": "mesa",
"temperature": 2,
"precipitation": "none",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Modified Wooded Badlands Plateau",
"color": 14204813,
"parent": "wooded_badlands_plateau",
"rainfall": 0
},
{
"id": 167,
"name": "modified_badlands_plateau",
"category": "mesa",
"temperature": 2,
"precipitation": "none",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Modified Badlands Plateau",
"color": 15905933,
"parent": "badlands_plateau",
"rainfall": 0
},
{
"id": 168,
"name": "bamboo_jungle",
"category": "jungle",
"temperature": 0.95,
"precipitation": "rain",
"depth": 0.1,
"dimension": "overworld",
"displayName": "Bamboo Jungle",
"color": 7769620,
"rainfall": 0.9
},
{
"id": 169,
"name": "bamboo_jungle_hills",
"category": "jungle",
"temperature": 0.95,
"precipitation": "rain",
"depth": 0.45,
"dimension": "overworld",
"displayName": "Bamboo Jungle Hills",
"color": 3884810,
"rainfall": 0.9
}
]
@@ -0,0 +1,946 @@
{"blocks":{"air":0,
"stone":1,
"granite":1,
"polished_granite":1,
"diorite":1,
"polished_diorite":1,
"andesite":1,
"polished_andesite":1,
"grass_block":1,
"dirt":1,
"coarse_dirt":1,
"podzol":1,
"cobblestone":1,
"oak_planks":1,
"spruce_planks":1,
"birch_planks":1,
"jungle_planks":1,
"acacia_planks":1,
"dark_oak_planks":1,
"oak_sapling":0,
"spruce_sapling":0,
"birch_sapling":0,
"jungle_sapling":0,
"acacia_sapling":0,
"dark_oak_sapling":0,
"bedrock":1,
"water":0,
"lava":0,
"sand":1,
"red_sand":1,
"gravel":1,
"gold_ore":1,
"iron_ore":1,
"coal_ore":1,
"oak_log":1,
"spruce_log":1,
"birch_log":1,
"jungle_log":1,
"acacia_log":1,
"dark_oak_log":1,
"stripped_spruce_log":1,
"stripped_birch_log":1,
"stripped_jungle_log":1,
"stripped_acacia_log":1,
"stripped_dark_oak_log":1,
"stripped_oak_log":1,
"oak_wood":1,
"spruce_wood":1,
"birch_wood":1,
"jungle_wood":1,
"acacia_wood":1,
"dark_oak_wood":1,
"stripped_oak_wood":1,
"stripped_spruce_wood":1,
"stripped_birch_wood":1,
"stripped_jungle_wood":1,
"stripped_acacia_wood":1,
"stripped_dark_oak_wood":1,
"oak_leaves":1,
"spruce_leaves":1,
"birch_leaves":1,
"jungle_leaves":1,
"acacia_leaves":1,
"dark_oak_leaves":1,
"sponge":1,
"wet_sponge":1,
"glass":1,
"lapis_ore":1,
"lapis_block":1,
"dispenser":1,
"sandstone":1,
"chiseled_sandstone":1,
"cut_sandstone":1,
"note_block":1,
"white_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"orange_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"magenta_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"light_blue_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"yellow_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"lime_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"pink_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"gray_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"light_gray_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"cyan_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"purple_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"blue_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"brown_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"green_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"red_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"black_bed":[3,2,3,2,2,3,2,3,4,5,4,5,5,4,5,4],
"powered_rail":0,
"detector_rail":0,
"sticky_piston":[6,7,8,9,10,11,1,1,1,1,1,1],
"cobweb":0,
"grass":0,
"fern":0,
"dead_bush":0,
"seagrass":0,
"tall_seagrass":0,
"piston":[6,7,8,9,10,11,1,1,1,1,1,1],
"piston_head":[13,13,12,12,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23],
"white_wool":1,
"orange_wool":1,
"magenta_wool":1,
"light_blue_wool":1,
"yellow_wool":1,
"lime_wool":1,
"pink_wool":1,
"gray_wool":1,
"light_gray_wool":1,
"cyan_wool":1,
"purple_wool":1,
"blue_wool":1,
"brown_wool":1,
"green_wool":1,
"red_wool":1,
"black_wool":1,
"moving_piston":0,
"dandelion":0,
"poppy":0,
"blue_orchid":0,
"allium":0,
"azure_bluet":0,
"red_tulip":0,
"orange_tulip":0,
"white_tulip":0,
"pink_tulip":0,
"oxeye_daisy":0,
"cornflower":0,
"wither_rose":0,
"lily_of_the_valley":0,
"brown_mushroom":0,
"red_mushroom":0,
"gold_block":1,
"iron_block":1,
"bricks":1,
"tnt":1,
"bookshelf":1,
"mossy_cobblestone":1,
"obsidian":1,
"torch":0,
"wall_torch":0,
"fire":0,
"spawner":1,
"oak_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"chest":[48,48,49,49,50,50,48,48,50,50,49,49,48,48,51,51,52,52,48,48,52,52,51,51],
"redstone_wire":0,
"diamond_ore":1,
"diamond_block":1,
"crafting_table":1,
"wheat":0,
"farmland":53,
"furnace":1,
"oak_sign":0,
"spruce_sign":0,
"birch_sign":0,
"acacia_sign":0,
"jungle_sign":0,
"dark_oak_sign":0,
"oak_door":[55,55,54,54,56,56,54,54,55,55,54,54,56,56,54,54,56,56,57,57,55,55,57,57,56,56,57,57,55,55,57,57,54,54,56,56,57,57,56,56,54,54,56,56,57,57,56,56,57,57,55,55,54,54,55,55,57,57,55,55,54,54,55,55],
"ladder":[54,54,57,57,56,56,55,55],
"rail":0,
"cobblestone_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"oak_wall_sign":0,
"spruce_wall_sign":0,
"birch_wall_sign":0,
"acacia_wall_sign":0,
"jungle_wall_sign":0,
"dark_oak_wall_sign":0,
"lever":0,
"stone_pressure_plate":0,
"iron_door":[55,55,54,54,56,56,54,54,55,55,54,54,56,56,54,54,56,56,57,57,55,55,57,57,56,56,57,57,55,55,57,57,54,54,56,56,57,57,56,56,54,54,56,56,57,57,56,56,57,57,55,55,54,54,55,55,57,57,55,55,54,54,55,55],
"oak_pressure_plate":0,
"spruce_pressure_plate":0,
"birch_pressure_plate":0,
"jungle_pressure_plate":0,
"acacia_pressure_plate":0,
"dark_oak_pressure_plate":0,
"redstone_ore":1,
"redstone_torch":0,
"redstone_wall_torch":0,
"stone_button":0,
"snow":[0,58,59,60,61,62,10,63],
"ice":1,
"snow_block":1,
"cactus":64,
"clay":1,
"sugar_cane":0,
"jukebox":1,
"oak_fence":[66,67,66,67,68,69,68,69,70,71,70,71,72,73,72,73,74,75,74,75,76,77,76,77,78,79,78,79,80,65,80,65],
"pumpkin":1,
"netherrack":1,
"soul_sand":63,
"glowstone":1,
"nether_portal":0,
"carved_pumpkin":1,
"jack_o_lantern":1,
"cake":[81,82,83,84,85,86,87],
"repeater":58,
"white_stained_glass":1,
"orange_stained_glass":1,
"magenta_stained_glass":1,
"light_blue_stained_glass":1,
"yellow_stained_glass":1,
"lime_stained_glass":1,
"pink_stained_glass":1,
"gray_stained_glass":1,
"light_gray_stained_glass":1,
"cyan_stained_glass":1,
"purple_stained_glass":1,
"blue_stained_glass":1,
"brown_stained_glass":1,
"green_stained_glass":1,
"red_stained_glass":1,
"black_stained_glass":1,
"oak_trapdoor":[54,54,54,54,89,89,89,89,54,54,54,54,88,88,88,88,57,57,57,57,89,89,89,89,57,57,57,57,88,88,88,88,56,56,56,56,89,89,89,89,56,56,56,56,88,88,88,88,55,55,55,55,89,89,89,89,55,55,55,55,88,88,88,88],
"spruce_trapdoor":[54,54,54,54,89,89,89,89,54,54,54,54,88,88,88,88,57,57,57,57,89,89,89,89,57,57,57,57,88,88,88,88,56,56,56,56,89,89,89,89,56,56,56,56,88,88,88,88,55,55,55,55,89,89,89,89,55,55,55,55,88,88,88,88],
"birch_trapdoor":[54,54,54,54,89,89,89,89,54,54,54,54,88,88,88,88,57,57,57,57,89,89,89,89,57,57,57,57,88,88,88,88,56,56,56,56,89,89,89,89,56,56,56,56,88,88,88,88,55,55,55,55,89,89,89,89,55,55,55,55,88,88,88,88],
"jungle_trapdoor":[54,54,54,54,89,89,89,89,54,54,54,54,88,88,88,88,57,57,57,57,89,89,89,89,57,57,57,57,88,88,88,88,56,56,56,56,89,89,89,89,56,56,56,56,88,88,88,88,55,55,55,55,89,89,89,89,55,55,55,55,88,88,88,88],
"acacia_trapdoor":[54,54,54,54,89,89,89,89,54,54,54,54,88,88,88,88,57,57,57,57,89,89,89,89,57,57,57,57,88,88,88,88,56,56,56,56,89,89,89,89,56,56,56,56,88,88,88,88,55,55,55,55,89,89,89,89,55,55,55,55,88,88,88,88],
"dark_oak_trapdoor":[54,54,54,54,89,89,89,89,54,54,54,54,88,88,88,88,57,57,57,57,89,89,89,89,57,57,57,57,88,88,88,88,56,56,56,56,89,89,89,89,56,56,56,56,88,88,88,88,55,55,55,55,89,89,89,89,55,55,55,55,88,88,88,88],
"stone_bricks":1,
"mossy_stone_bricks":1,
"cracked_stone_bricks":1,
"chiseled_stone_bricks":1,
"infested_stone":1,
"infested_cobblestone":1,
"infested_stone_bricks":1,
"infested_mossy_stone_bricks":1,
"infested_cracked_stone_bricks":1,
"infested_chiseled_stone_bricks":1,
"brown_mushroom_block":1,
"red_mushroom_block":1,
"mushroom_stem":1,
"iron_bars":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"melon":1,
"attached_pumpkin_stem":0,
"attached_melon_stem":0,
"pumpkin_stem":0,
"melon_stem":0,
"vine":0,
"oak_fence_gate":[0,0,72,72,0,0,72,72,0,0,72,72,0,0,72,72,0,0,75,75,0,0,75,75,0,0,75,75,0,0,75,75],
"brick_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"stone_brick_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"mycelium":1,
"lily_pad":106,
"nether_bricks":1,
"nether_brick_fence":[66,67,66,67,68,69,68,69,70,71,70,71,72,73,72,73,74,75,74,75,76,77,76,77,78,79,78,79,80,65,80,65],
"nether_brick_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"nether_wart":0,
"enchanting_table":10,
"brewing_stand":107,
"cauldron":108,
"end_portal":0,
"end_portal_frame":[110,110,110,110,109,109,109,109],
"end_stone":1,
"dragon_egg":111,
"redstone_lamp":1,
"cocoa":[112,113,114,115,116,117,118,119,120,121,122,123],
"sandstone_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"emerald_ore":1,
"ender_chest":48,
"tripwire_hook":0,
"tripwire":0,
"emerald_block":1,
"spruce_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"birch_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"jungle_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"command_block":1,
"beacon":1,
"cobblestone_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"mossy_cobblestone_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"flower_pot":156,
"potted_oak_sapling":156,
"potted_spruce_sapling":156,
"potted_birch_sapling":156,
"potted_jungle_sapling":156,
"potted_acacia_sapling":156,
"potted_dark_oak_sapling":156,
"potted_fern":156,
"potted_dandelion":156,
"potted_poppy":156,
"potted_blue_orchid":156,
"potted_allium":156,
"potted_azure_bluet":156,
"potted_red_tulip":156,
"potted_orange_tulip":156,
"potted_white_tulip":156,
"potted_pink_tulip":156,
"potted_oxeye_daisy":156,
"potted_cornflower":156,
"potted_lily_of_the_valley":156,
"potted_wither_rose":156,
"potted_red_mushroom":156,
"potted_brown_mushroom":156,
"potted_dead_bush":156,
"potted_cactus":156,
"carrots":0,
"potatoes":0,
"oak_button":0,
"spruce_button":0,
"birch_button":0,
"jungle_button":0,
"acacia_button":0,
"dark_oak_button":0,
"skeleton_skull":157,
"skeleton_wall_skull":[158,159,160,161],
"wither_skeleton_skull":157,
"wither_skeleton_wall_skull":[158,159,160,161],
"zombie_head":157,
"zombie_wall_head":[158,159,160,161],
"player_head":157,
"player_wall_head":[158,159,160,161],
"creeper_head":157,
"creeper_wall_head":[158,159,160,161],
"dragon_head":157,
"dragon_wall_head":[158,159,160,161],
"anvil":[162,162,163,163],
"chipped_anvil":[162,162,163,163],
"damaged_anvil":[162,162,163,163],
"trapped_chest":[48,48,49,49,50,50,48,48,50,50,49,49,48,48,51,51,52,52,48,48,52,52,51,51],
"light_weighted_pressure_plate":0,
"heavy_weighted_pressure_plate":0,
"comparator":58,
"daylight_detector":60,
"redstone_block":1,
"nether_quartz_ore":1,
"hopper":[164,165,166,167,168,164,165,166,167,168],
"quartz_block":1,
"chiseled_quartz_block":1,
"quartz_pillar":1,
"quartz_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"activator_rail":0,
"dropper":1,
"white_terracotta":1,
"orange_terracotta":1,
"magenta_terracotta":1,
"light_blue_terracotta":1,
"yellow_terracotta":1,
"lime_terracotta":1,
"pink_terracotta":1,
"gray_terracotta":1,
"light_gray_terracotta":1,
"cyan_terracotta":1,
"purple_terracotta":1,
"blue_terracotta":1,
"brown_terracotta":1,
"green_terracotta":1,
"red_terracotta":1,
"black_terracotta":1,
"white_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"orange_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"magenta_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"light_blue_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"yellow_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"lime_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"pink_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"gray_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"light_gray_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"cyan_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"purple_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"blue_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"brown_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"green_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"red_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"black_stained_glass_pane":[91,92,91,92,93,94,93,94,95,96,95,96,97,98,97,98,99,100,99,100,101,102,101,102,103,104,103,104,105,90,105,90],
"acacia_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"dark_oak_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"slime_block":1,
"barrier":1,
"iron_trapdoor":[54,54,54,54,89,89,89,89,54,54,54,54,88,88,88,88,57,57,57,57,89,89,89,89,57,57,57,57,88,88,88,88,56,56,56,56,89,89,89,89,56,56,56,56,88,88,88,88,55,55,55,55,89,89,89,89,55,55,55,55,88,88,88,88],
"prismarine":1,
"prismarine_bricks":1,
"dark_prismarine":1,
"prismarine_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"prismarine_brick_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"dark_prismarine_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"prismarine_slab":[169,169,61,61,1,1],
"prismarine_brick_slab":[169,169,61,61,1,1],
"dark_prismarine_slab":[169,169,61,61,1,1],
"sea_lantern":1,
"hay_block":1,
"white_carpet":170,
"orange_carpet":170,
"magenta_carpet":170,
"light_blue_carpet":170,
"yellow_carpet":170,
"lime_carpet":170,
"pink_carpet":170,
"gray_carpet":170,
"light_gray_carpet":170,
"cyan_carpet":170,
"purple_carpet":170,
"blue_carpet":170,
"brown_carpet":170,
"green_carpet":170,
"red_carpet":170,
"black_carpet":170,
"terracotta":1,
"coal_block":1,
"packed_ice":1,
"sunflower":0,
"lilac":0,
"rose_bush":0,
"peony":0,
"tall_grass":0,
"large_fern":0,
"white_banner":0,
"orange_banner":0,
"magenta_banner":0,
"light_blue_banner":0,
"yellow_banner":0,
"lime_banner":0,
"pink_banner":0,
"gray_banner":0,
"light_gray_banner":0,
"cyan_banner":0,
"purple_banner":0,
"blue_banner":0,
"brown_banner":0,
"green_banner":0,
"red_banner":0,
"black_banner":0,
"white_wall_banner":0,
"orange_wall_banner":0,
"magenta_wall_banner":0,
"light_blue_wall_banner":0,
"yellow_wall_banner":0,
"lime_wall_banner":0,
"pink_wall_banner":0,
"gray_wall_banner":0,
"light_gray_wall_banner":0,
"cyan_wall_banner":0,
"purple_wall_banner":0,
"blue_wall_banner":0,
"brown_wall_banner":0,
"green_wall_banner":0,
"red_wall_banner":0,
"black_wall_banner":0,
"red_sandstone":1,
"chiseled_red_sandstone":1,
"cut_red_sandstone":1,
"red_sandstone_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"oak_slab":[169,169,61,61,1,1],
"spruce_slab":[169,169,61,61,1,1],
"birch_slab":[169,169,61,61,1,1],
"jungle_slab":[169,169,61,61,1,1],
"acacia_slab":[169,169,61,61,1,1],
"dark_oak_slab":[169,169,61,61,1,1],
"stone_slab":[169,169,61,61,1,1],
"smooth_stone_slab":[169,169,61,61,1,1],
"sandstone_slab":[169,169,61,61,1,1],
"cut_sandstone_slab":[169,169,61,61,1,1],
"petrified_oak_slab":[169,169,61,61,1,1],
"cobblestone_slab":[169,169,61,61,1,1],
"brick_slab":[169,169,61,61,1,1],
"stone_brick_slab":[169,169,61,61,1,1],
"nether_brick_slab":[169,169,61,61,1,1],
"quartz_slab":[169,169,61,61,1,1],
"red_sandstone_slab":[169,169,61,61,1,1],
"cut_red_sandstone_slab":[169,169,61,61,1,1],
"purpur_slab":[169,169,61,61,1,1],
"smooth_stone":1,
"smooth_sandstone":1,
"smooth_quartz":1,
"smooth_red_sandstone":1,
"spruce_fence_gate":[0,0,72,72,0,0,72,72,0,0,72,72,0,0,72,72,0,0,75,75,0,0,75,75,0,0,75,75,0,0,75,75],
"birch_fence_gate":[0,0,72,72,0,0,72,72,0,0,72,72,0,0,72,72,0,0,75,75,0,0,75,75,0,0,75,75,0,0,75,75],
"jungle_fence_gate":[0,0,72,72,0,0,72,72,0,0,72,72,0,0,72,72,0,0,75,75,0,0,75,75,0,0,75,75,0,0,75,75],
"acacia_fence_gate":[0,0,72,72,0,0,72,72,0,0,72,72,0,0,72,72,0,0,75,75,0,0,75,75,0,0,75,75,0,0,75,75],
"dark_oak_fence_gate":[0,0,72,72,0,0,72,72,0,0,72,72,0,0,72,72,0,0,75,75,0,0,75,75,0,0,75,75,0,0,75,75],
"spruce_fence":[66,67,66,67,68,69,68,69,70,71,70,71,72,73,72,73,74,75,74,75,76,77,76,77,78,79,78,79,80,65,80,65],
"birch_fence":[66,67,66,67,68,69,68,69,70,71,70,71,72,73,72,73,74,75,74,75,76,77,76,77,78,79,78,79,80,65,80,65],
"jungle_fence":[66,67,66,67,68,69,68,69,70,71,70,71,72,73,72,73,74,75,74,75,76,77,76,77,78,79,78,79,80,65,80,65],
"acacia_fence":[66,67,66,67,68,69,68,69,70,71,70,71,72,73,72,73,74,75,74,75,76,77,76,77,78,79,78,79,80,65,80,65],
"dark_oak_fence":[66,67,66,67,68,69,68,69,70,71,70,71,72,73,72,73,74,75,74,75,76,77,76,77,78,79,78,79,80,65,80,65],
"spruce_door":[55,55,54,54,56,56,54,54,55,55,54,54,56,56,54,54,56,56,57,57,55,55,57,57,56,56,57,57,55,55,57,57,54,54,56,56,57,57,56,56,54,54,56,56,57,57,56,56,57,57,55,55,54,54,55,55,57,57,55,55,54,54,55,55],
"birch_door":[55,55,54,54,56,56,54,54,55,55,54,54,56,56,54,54,56,56,57,57,55,55,57,57,56,56,57,57,55,55,57,57,54,54,56,56,57,57,56,56,54,54,56,56,57,57,56,56,57,57,55,55,54,54,55,55,57,57,55,55,54,54,55,55],
"jungle_door":[55,55,54,54,56,56,54,54,55,55,54,54,56,56,54,54,56,56,57,57,55,55,57,57,56,56,57,57,55,55,57,57,54,54,56,56,57,57,56,56,54,54,56,56,57,57,56,56,57,57,55,55,54,54,55,55,57,57,55,55,54,54,55,55],
"acacia_door":[55,55,54,54,56,56,54,54,55,55,54,54,56,56,54,54,56,56,57,57,55,55,57,57,56,56,57,57,55,55,57,57,54,54,56,56,57,57,56,56,54,54,56,56,57,57,56,56,57,57,55,55,54,54,55,55,57,57,55,55,54,54,55,55],
"dark_oak_door":[55,55,54,54,56,56,54,54,55,55,54,54,56,56,54,54,56,56,57,57,55,55,57,57,56,56,57,57,55,55,57,57,54,54,56,56,57,57,56,56,54,54,56,56,57,57,56,56,57,57,55,55,54,54,55,55,57,57,55,55,54,54,55,55],
"end_rod":[172,173,172,173,171,171],
"chorus_plant":[175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,174],
"chorus_flower":1,
"purpur_block":1,
"purpur_pillar":1,
"purpur_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"end_stone_bricks":1,
"beetroots":0,
"grass_path":53,
"end_gateway":0,
"repeating_command_block":1,
"chain_command_block":1,
"frosted_ice":1,
"magma_block":1,
"nether_wart_block":1,
"red_nether_bricks":1,
"bone_block":1,
"structure_void":0,
"observer":1,
"shulker_box":1,
"white_shulker_box":1,
"orange_shulker_box":1,
"magenta_shulker_box":1,
"light_blue_shulker_box":1,
"yellow_shulker_box":1,
"lime_shulker_box":1,
"pink_shulker_box":1,
"gray_shulker_box":1,
"light_gray_shulker_box":1,
"cyan_shulker_box":1,
"purple_shulker_box":1,
"blue_shulker_box":1,
"brown_shulker_box":1,
"green_shulker_box":1,
"red_shulker_box":1,
"black_shulker_box":1,
"white_glazed_terracotta":1,
"orange_glazed_terracotta":1,
"magenta_glazed_terracotta":1,
"light_blue_glazed_terracotta":1,
"yellow_glazed_terracotta":1,
"lime_glazed_terracotta":1,
"pink_glazed_terracotta":1,
"gray_glazed_terracotta":1,
"light_gray_glazed_terracotta":1,
"cyan_glazed_terracotta":1,
"purple_glazed_terracotta":1,
"blue_glazed_terracotta":1,
"brown_glazed_terracotta":1,
"green_glazed_terracotta":1,
"red_glazed_terracotta":1,
"black_glazed_terracotta":1,
"white_concrete":1,
"orange_concrete":1,
"magenta_concrete":1,
"light_blue_concrete":1,
"yellow_concrete":1,
"lime_concrete":1,
"pink_concrete":1,
"gray_concrete":1,
"light_gray_concrete":1,
"cyan_concrete":1,
"purple_concrete":1,
"blue_concrete":1,
"brown_concrete":1,
"green_concrete":1,
"red_concrete":1,
"black_concrete":1,
"white_concrete_powder":1,
"orange_concrete_powder":1,
"magenta_concrete_powder":1,
"light_blue_concrete_powder":1,
"yellow_concrete_powder":1,
"lime_concrete_powder":1,
"pink_concrete_powder":1,
"gray_concrete_powder":1,
"light_gray_concrete_powder":1,
"cyan_concrete_powder":1,
"purple_concrete_powder":1,
"blue_concrete_powder":1,
"brown_concrete_powder":1,
"green_concrete_powder":1,
"red_concrete_powder":1,
"black_concrete_powder":1,
"kelp":0,
"kelp_plant":0,
"dried_kelp_block":1,
"turtle_egg":[238,238,238,239,239,239,239,239,239,239,239,239],
"dead_tube_coral_block":1,
"dead_brain_coral_block":1,
"dead_bubble_coral_block":1,
"dead_fire_coral_block":1,
"dead_horn_coral_block":1,
"tube_coral_block":1,
"brain_coral_block":1,
"bubble_coral_block":1,
"fire_coral_block":1,
"horn_coral_block":1,
"dead_tube_coral":0,
"dead_brain_coral":0,
"dead_bubble_coral":0,
"dead_fire_coral":0,
"dead_horn_coral":0,
"tube_coral":0,
"brain_coral":0,
"bubble_coral":0,
"fire_coral":0,
"horn_coral":0,
"dead_tube_coral_fan":0,
"dead_brain_coral_fan":0,
"dead_bubble_coral_fan":0,
"dead_fire_coral_fan":0,
"dead_horn_coral_fan":0,
"tube_coral_fan":0,
"brain_coral_fan":0,
"bubble_coral_fan":0,
"fire_coral_fan":0,
"horn_coral_fan":0,
"dead_tube_coral_wall_fan":0,
"dead_brain_coral_wall_fan":0,
"dead_bubble_coral_wall_fan":0,
"dead_fire_coral_wall_fan":0,
"dead_horn_coral_wall_fan":0,
"tube_coral_wall_fan":0,
"brain_coral_wall_fan":0,
"bubble_coral_wall_fan":0,
"fire_coral_wall_fan":0,
"horn_coral_wall_fan":0,
"sea_pickle":[240,240,241,241,242,242,243,243],
"blue_ice":1,
"conduit":244,
"bamboo_sapling":0,
"bamboo":245,
"potted_bamboo":156,
"void_air":0,
"cave_air":0,
"bubble_column":0,
"polished_granite_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"smooth_red_sandstone_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"mossy_stone_brick_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"polished_diorite_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"mossy_cobblestone_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"end_stone_brick_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"stone_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"smooth_sandstone_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"smooth_quartz_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"granite_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"andesite_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"red_nether_brick_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"polished_andesite_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"diorite_stairs":[25,25,26,26,27,27,28,28,29,29,24,24,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,36,36,26,26,38,38,28,28,45,45,41,41,30,30,43,43,32,32,46,46,27,27,35,35,29,29,37,37,47,47,31,31,40,40,33,33,42,42],
"polished_granite_slab":[169,169,61,61,1,1],
"smooth_red_sandstone_slab":[169,169,61,61,1,1],
"mossy_stone_brick_slab":[169,169,61,61,1,1],
"polished_diorite_slab":[169,169,61,61,1,1],
"mossy_cobblestone_slab":[169,169,61,61,1,1],
"end_stone_brick_slab":[169,169,61,61,1,1],
"smooth_sandstone_slab":[169,169,61,61,1,1],
"smooth_quartz_slab":[169,169,61,61,1,1],
"granite_slab":[169,169,61,61,1,1],
"andesite_slab":[169,169,61,61,1,1],
"red_nether_brick_slab":[169,169,61,61,1,1],
"polished_andesite_slab":[169,169,61,61,1,1],
"diorite_slab":[169,169,61,61,1,1],
"brick_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"prismarine_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"red_sandstone_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"mossy_stone_brick_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"granite_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"stone_brick_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"nether_brick_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"andesite_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"red_nether_brick_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"sandstone_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"end_stone_brick_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"diorite_wall":[125,126,125,126,127,128,127,128,129,130,129,130,131,132,131,132,133,134,133,134,135,136,135,136,137,138,137,138,139,140,139,140,141,142,141,142,143,144,143,144,145,146,145,146,147,148,147,148,149,150,149,150,151,152,151,152,153,124,153,124,154,155,154,155],
"scaffolding":246,
"loom":1,
"barrel":1,
"smoker":1,
"blast_furnace":1,
"cartography_table":1,
"fletching_table":1,
"grindstone":[248,248,249,249,247,250,251,252,253,253,254,254],
"lectern":255,
"smithing_table":1,
"stonecutter":256,
"bell":[257,257,258,258,259,259,259,259,260,261,262,263,264,264,265,265],
"lantern":[267,266],
"campfire":268,
"sweet_berry_bush":0,
"structure_block":1,
"jigsaw":1,
"composter":269},
"shapes":{"0":[],
"1":[[0.0,0.0,0.0,1.0,1.0,1.0]],
"2":[[0.0,0.0,0.8125,0.1875,0.5625,1.0],[0.0,0.1875,0.0,1.0,0.5625,0.8125],[0.1875,0.1875,0.8125,1.0,0.5625,1.0],[0.8125,0.0,0.8125,1.0,0.1875,1.0]],
"3":[[0.0,0.0,0.0,0.1875,0.5625,0.1875],[0.0,0.1875,0.1875,1.0,0.5625,1.0],[0.1875,0.1875,0.0,1.0,0.5625,0.1875],[0.8125,0.0,0.0,1.0,0.1875,0.1875]],
"4":[[0.0,0.0,0.0,0.1875,0.5625,0.1875],[0.0,0.0,0.8125,0.1875,0.5625,1.0],[0.0,0.1875,0.1875,1.0,0.5625,0.8125],[0.1875,0.1875,0.0,1.0,0.5625,0.1875],[0.1875,0.1875,0.8125,1.0,0.5625,1.0]],
"5":[[0.0,0.1875,0.0,1.0,0.5625,1.0],[0.8125,0.0,0.0,1.0,0.1875,0.1875],[0.8125,0.0,0.8125,1.0,0.1875,1.0]],
"6":[[0.0,0.0,0.25,1.0,1.0,1.0]],
"7":[[0.0,0.0,0.0,0.75,1.0,1.0]],
"8":[[0.0,0.0,0.0,1.0,1.0,0.75]],
"9":[[0.25,0.0,0.0,1.0,1.0,1.0]],
"10":[[0.0,0.0,0.0,1.0,0.75,1.0]],
"11":[[0.0,0.25,0.0,1.0,1.0,1.0]],
"12":[[0.0,0.0,0.0,1.0,1.0,0.25],[0.375,0.375,0.25,0.625,0.625,1.25]],
"13":[[0.0,0.0,0.0,1.0,1.0,0.25],[0.375,0.375,0.25,0.625,0.625,1.0]],
"14":[[0.0,0.375,0.375,1.0,0.625,0.625],[0.75,0.0,0.0,1.0,0.375,1.0],[0.75,0.375,0.0,1.0,1.0,0.375],[0.75,0.375,0.625,1.0,1.0,1.0],[0.75,0.625,0.375,1.0,1.0,0.625]],
"15":[[-0.25,0.375,0.375,1.0,0.625,0.625],[0.75,0.0,0.0,1.0,0.375,1.0],[0.75,0.375,0.0,1.0,1.0,0.375],[0.75,0.375,0.625,1.0,1.0,1.0],[0.75,0.625,0.375,1.0,1.0,0.625]],
"16":[[0.0,0.0,0.75,1.0,1.0,1.0],[0.375,0.375,0.0,0.625,0.625,0.75]],
"17":[[0.0,0.0,0.75,1.0,1.0,1.0],[0.375,0.375,-0.25,0.625,0.625,0.75]],
"18":[[0.0,0.0,0.0,0.25,1.0,1.0],[0.25,0.375,0.375,1.0,0.625,0.625]],
"19":[[0.0,0.0,0.0,0.25,1.0,1.0],[0.25,0.375,0.375,1.25,0.625,0.625]],
"20":[[0.0,0.75,0.0,1.0,1.0,1.0],[0.375,0.0,0.375,0.625,0.75,0.625]],
"21":[[0.0,0.75,0.0,1.0,1.0,1.0],[0.375,-0.25,0.375,0.625,0.75,0.625]],
"22":[[0.0,0.0,0.0,1.0,0.25,1.0],[0.375,0.25,0.375,0.625,1.0,0.625]],
"23":[[0.0,0.0,0.0,1.0,0.25,1.0],[0.375,0.25,0.375,0.625,1.25,0.625]],
"24":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.0,0.5,0.0,1.0,1.0,0.5]],
"25":[[0.0,0.0,0.0,1.0,1.0,0.5],[0.0,0.5,0.5,1.0,1.0,1.0]],
"26":[[0.0,0.0,0.0,0.5,1.0,1.0],[0.5,0.0,0.0,1.0,1.0,0.5],[0.5,0.5,0.5,1.0,1.0,1.0]],
"27":[[0.0,0.0,0.0,1.0,1.0,0.5],[0.0,0.5,0.5,1.0,1.0,1.0],[0.5,0.0,0.5,1.0,0.5,1.0]],
"28":[[0.0,0.0,0.0,0.5,1.0,0.5],[0.0,0.5,0.5,1.0,1.0,1.0],[0.5,0.5,0.0,1.0,1.0,0.5]],
"29":[[0.0,0.5,0.0,1.0,1.0,1.0],[0.5,0.0,0.0,1.0,0.5,0.5]],
"30":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.0,0.5,0.0,0.5,1.0,1.0],[0.5,0.5,0.0,1.0,1.0,0.5]],
"31":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.0,0.5,0.0,1.0,1.0,0.5],[0.5,0.5,0.5,1.0,1.0,1.0]],
"32":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.0,0.5,0.0,0.5,1.0,0.5]],
"33":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.5,0.5,0.0,1.0,1.0,0.5]],
"34":[[0.0,0.0,0.5,1.0,1.0,1.0],[0.0,0.5,0.0,1.0,1.0,0.5]],
"35":[[0.0,0.0,0.5,1.0,1.0,1.0],[0.0,0.5,0.0,1.0,1.0,0.5],[0.5,0.0,0.0,1.0,0.5,0.5]],
"36":[[0.0,0.0,0.0,0.5,1.0,1.0],[0.5,0.0,0.5,1.0,1.0,1.0],[0.5,0.5,0.0,1.0,1.0,0.5]],
"37":[[0.0,0.5,0.0,1.0,1.0,1.0],[0.5,0.0,0.5,1.0,0.5,1.0]],
"38":[[0.0,0.0,0.5,0.5,1.0,1.0],[0.0,0.5,0.0,1.0,1.0,0.5],[0.5,0.5,0.5,1.0,1.0,1.0]],
"39":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.0,0.5,0.5,1.0,1.0,1.0]],
"40":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.0,0.5,0.5,1.0,1.0,1.0],[0.5,0.5,0.0,1.0,1.0,0.5]],
"41":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.0,0.5,0.0,0.5,1.0,1.0],[0.5,0.5,0.5,1.0,1.0,1.0]],
"42":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.5,0.5,0.5,1.0,1.0,1.0]],
"43":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.0,0.5,0.5,0.5,1.0,1.0]],
"44":[[0.0,0.0,0.0,0.5,1.0,1.0],[0.5,0.5,0.0,1.0,1.0,1.0]],
"45":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.0,0.5,0.0,0.5,1.0,1.0]],
"46":[[0.0,0.5,0.0,1.0,1.0,1.0],[0.5,0.0,0.0,1.0,0.5,1.0]],
"47":[[0.0,0.0,0.0,1.0,0.5,1.0],[0.5,0.5,0.0,1.0,1.0,1.0]],
"48":[[0.0625,0.0,0.0625,0.9375,0.875,0.9375]],
"49":[[0.0625,0.0,0.0625,1.0,0.875,0.9375]],
"50":[[0.0,0.0,0.0625,0.9375,0.875,0.9375]],
"51":[[0.0625,0.0,0.0,0.9375,0.875,0.9375]],
"52":[[0.0625,0.0,0.0625,0.9375,0.875,1.0]],
"53":[[0.0,0.0,0.0,1.0,0.9375,1.0]],
"54":[[0.0,0.0,0.8125,1.0,1.0,1.0]],
"55":[[0.0,0.0,0.0,0.1875,1.0,1.0]],
"56":[[0.8125,0.0,0.0,1.0,1.0,1.0]],
"57":[[0.0,0.0,0.0,1.0,1.0,0.1875]],
"58":[[0.0,0.0,0.0,1.0,0.125,1.0]],
"59":[[0.0,0.0,0.0,1.0,0.25,1.0]],
"60":[[0.0,0.0,0.0,1.0,0.375,1.0]],
"61":[[0.0,0.0,0.0,1.0,0.5,1.0]],
"62":[[0.0,0.0,0.0,1.0,0.625,1.0]],
"63":[[0.0,0.0,0.0,1.0,0.875,1.0]],
"64":[[0.0625,0.0,0.0625,0.9375,0.9375,0.9375]],
"65":[[0.375,0.0,0.375,0.625,1.5,0.625]],
"66":[[0.0,0.0,0.375,1.0,1.5,0.625],[0.375,0.0,0.0,0.625,1.5,0.375],[0.375,0.0,0.625,0.625,1.5,1.0]],
"67":[[0.375,0.0,0.0,0.625,1.5,1.0],[0.625,0.0,0.375,1.0,1.5,0.625]],
"68":[[0.0,0.0,0.375,1.0,1.5,0.625],[0.375,0.0,0.0,0.625,1.5,0.375]],
"69":[[0.375,0.0,0.0,0.625,1.5,0.625],[0.625,0.0,0.375,1.0,1.5,0.625]],
"70":[[0.0,0.0,0.375,1.0,1.5,0.625],[0.375,0.0,0.625,0.625,1.5,1.0]],
"71":[[0.375,0.0,0.375,0.625,1.5,1.0],[0.625,0.0,0.375,1.0,1.5,0.625]],
"72":[[0.0,0.0,0.375,1.0,1.5,0.625]],
"73":[[0.375,0.0,0.375,1.0,1.5,0.625]],
"74":[[0.0,0.0,0.375,0.625,1.5,0.625],[0.375,0.0,0.0,0.625,1.5,0.375],[0.375,0.0,0.625,0.625,1.5,1.0]],
"75":[[0.375,0.0,0.0,0.625,1.5,1.0]],
"76":[[0.0,0.0,0.375,0.625,1.5,0.625],[0.375,0.0,0.0,0.625,1.5,0.375]],
"77":[[0.375,0.0,0.0,0.625,1.5,0.625]],
"78":[[0.0,0.0,0.375,0.625,1.5,0.625],[0.375,0.0,0.625,0.625,1.5,1.0]],
"79":[[0.375,0.0,0.375,0.625,1.5,1.0]],
"80":[[0.0,0.0,0.375,0.625,1.5,0.625]],
"81":[[0.0625,0.0,0.0625,0.9375,0.5,0.9375]],
"82":[[0.1875,0.0,0.0625,0.9375,0.5,0.9375]],
"83":[[0.3125,0.0,0.0625,0.9375,0.5,0.9375]],
"84":[[0.4375,0.0,0.0625,0.9375,0.5,0.9375]],
"85":[[0.5625,0.0,0.0625,0.9375,0.5,0.9375]],
"86":[[0.6875,0.0,0.0625,0.9375,0.5,0.9375]],
"87":[[0.8125,0.0,0.0625,0.9375,0.5,0.9375]],
"88":[[0.0,0.0,0.0,1.0,0.1875,1.0]],
"89":[[0.0,0.8125,0.0,1.0,1.0,1.0]],
"90":[[0.4375,0.0,0.4375,0.5625,1.0,0.5625]],
"91":[[0.0,0.0,0.4375,1.0,1.0,0.5625],[0.4375,0.0,0.0,0.5625,1.0,0.4375],[0.4375,0.0,0.5625,0.5625,1.0,1.0]],
"92":[[0.4375,0.0,0.0,0.5625,1.0,1.0],[0.5625,0.0,0.4375,1.0,1.0,0.5625]],
"93":[[0.0,0.0,0.4375,1.0,1.0,0.5625],[0.4375,0.0,0.0,0.5625,1.0,0.4375]],
"94":[[0.4375,0.0,0.0,0.5625,1.0,0.5625],[0.5625,0.0,0.4375,1.0,1.0,0.5625]],
"95":[[0.0,0.0,0.4375,1.0,1.0,0.5625],[0.4375,0.0,0.5625,0.5625,1.0,1.0]],
"96":[[0.4375,0.0,0.4375,0.5625,1.0,1.0],[0.5625,0.0,0.4375,1.0,1.0,0.5625]],
"97":[[0.0,0.0,0.4375,1.0,1.0,0.5625]],
"98":[[0.4375,0.0,0.4375,1.0,1.0,0.5625]],
"99":[[0.0,0.0,0.4375,0.5625,1.0,0.5625],[0.4375,0.0,0.0,0.5625,1.0,0.4375],[0.4375,0.0,0.5625,0.5625,1.0,1.0]],
"100":[[0.4375,0.0,0.0,0.5625,1.0,1.0]],
"101":[[0.0,0.0,0.4375,0.5625,1.0,0.5625],[0.4375,0.0,0.0,0.5625,1.0,0.4375]],
"102":[[0.4375,0.0,0.0,0.5625,1.0,0.5625]],
"103":[[0.0,0.0,0.4375,0.5625,1.0,0.5625],[0.4375,0.0,0.5625,0.5625,1.0,1.0]],
"104":[[0.4375,0.0,0.4375,0.5625,1.0,1.0]],
"105":[[0.0,0.0,0.4375,0.5625,1.0,0.5625]],
"106":[[0.0625,0.0,0.0625,0.9375,0.09375,0.9375]],
"107":[[0.0625,0.0,0.0625,0.9375,0.125,0.9375],[0.4375,0.125,0.4375,0.5625,0.875,0.5625]],
"108":[[0.0,0.0,0.0,0.125,1.0,0.25],[0.0,0.0,0.75,0.125,1.0,1.0],[0.0,0.1875,0.25,1.0,0.25,0.75],[0.0,0.25,0.25,0.125,1.0,0.75],[0.125,0.0,0.0,0.25,1.0,0.125],[0.125,0.0,0.875,0.25,1.0,1.0],[0.125,0.1875,0.125,1.0,0.25,0.25],[0.125,0.1875,0.75,1.0,0.25,0.875],[0.25,0.1875,0.0,1.0,1.0,0.125],[0.25,0.1875,0.875,1.0,1.0,1.0],[0.75,0.0,0.0,1.0,0.1875,0.125],[0.75,0.0,0.875,1.0,0.1875,1.0],[0.875,0.0,0.125,1.0,0.1875,0.25],[0.875,0.0,0.75,1.0,0.1875,0.875],[0.875,0.25,0.125,1.0,1.0,0.875]],
"109":[[0.0,0.0,0.0,1.0,0.8125,1.0]],
"110":[[0.0,0.0,0.0,1.0,0.8125,1.0],[0.25,0.8125,0.25,0.75,1.0,0.75]],
"111":[[0.0625,0.0,0.0625,0.9375,1.0,0.9375]],
"112":[[0.375,0.4375,0.0625,0.625,0.75,0.3125]],
"113":[[0.375,0.4375,0.6875,0.625,0.75,0.9375]],
"114":[[0.0625,0.4375,0.375,0.3125,0.75,0.625]],
"115":[[0.6875,0.4375,0.375,0.9375,0.75,0.625]],
"116":[[0.3125,0.3125,0.0625,0.6875,0.75,0.4375]],
"117":[[0.3125,0.3125,0.5625,0.6875,0.75,0.9375]],
"118":[[0.0625,0.3125,0.3125,0.4375,0.75,0.6875]],
"119":[[0.5625,0.3125,0.3125,0.9375,0.75,0.6875]],
"120":[[0.25,0.1875,0.0625,0.75,0.75,0.5625]],
"121":[[0.25,0.1875,0.4375,0.75,0.75,0.9375]],
"122":[[0.0625,0.1875,0.25,0.5625,0.75,0.75]],
"123":[[0.4375,0.1875,0.25,0.9375,0.75,0.75]],
"124":[[0.25,0.0,0.25,0.75,1.5,0.75]],
"125":[[0.0,0.0,0.3125,1.0,1.5,0.6875],[0.25,0.0,0.25,0.75,1.5,0.3125],[0.25,0.0,0.6875,0.75,1.5,0.75],[0.3125,0.0,0.0,0.6875,1.5,0.25],[0.3125,0.0,0.75,0.6875,1.5,1.0]],
"126":[[0.25,0.0,0.25,0.75,1.5,0.75],[0.3125,0.0,0.0,0.6875,1.5,0.25],[0.3125,0.0,0.75,0.6875,1.5,1.0],[0.75,0.0,0.3125,1.0,1.5,0.6875]],
"127":[[0.0,0.0,0.3125,1.0,1.5,0.6875],[0.3125,0.0,0.0,0.6875,1.5,0.3125],[0.3125,0.0,0.6875,0.6875,1.5,1.0]],
"128":[[0.3125,0.0,0.0,0.6875,1.5,1.0],[0.6875,0.0,0.3125,1.0,1.5,0.6875]],
"129":[[0.0,0.0,0.3125,1.0,1.5,0.6875],[0.25,0.0,0.25,0.75,1.5,0.3125],[0.25,0.0,0.6875,0.75,1.5,0.75],[0.3125,0.0,0.0,0.6875,1.5,0.25]],
"130":[[0.25,0.0,0.25,0.75,1.5,0.75],[0.3125,0.0,0.0,0.6875,1.5,0.25],[0.75,0.0,0.3125,1.0,1.5,0.6875]],
"131":[[0.0,0.0,0.3125,1.0,1.5,0.6875],[0.3125,0.0,0.0,0.6875,1.5,0.3125]],
"132":[[0.3125,0.0,0.0,0.6875,1.5,0.6875],[0.6875,0.0,0.3125,1.0,1.5,0.6875]],
"133":[[0.0,0.0,0.3125,1.0,1.5,0.6875],[0.25,0.0,0.25,0.75,1.5,0.3125],[0.25,0.0,0.6875,0.75,1.5,0.75],[0.3125,0.0,0.75,0.6875,1.5,1.0]],
"134":[[0.25,0.0,0.25,0.75,1.5,0.75],[0.3125,0.0,0.75,0.6875,1.5,1.0],[0.75,0.0,0.3125,1.0,1.5,0.6875]],
"135":[[0.0,0.0,0.3125,1.0,1.5,0.6875],[0.3125,0.0,0.6875,0.6875,1.5,1.0]],
"136":[[0.3125,0.0,0.3125,0.6875,1.5,1.0],[0.6875,0.0,0.3125,1.0,1.5,0.6875]],
"137":[[0.0,0.0,0.3125,1.0,1.5,0.6875],[0.25,0.0,0.25,0.75,1.5,0.3125],[0.25,0.0,0.6875,0.75,1.5,0.75]],
"138":[[0.25,0.0,0.25,0.75,1.5,0.75],[0.75,0.0,0.3125,1.0,1.5,0.6875]],
"139":[[0.0,0.0,0.3125,1.0,1.5,0.6875]],
"140":[[0.3125,0.0,0.3125,1.0,1.5,0.6875]],
"141":[[0.0,0.0,0.3125,0.75,1.5,0.6875],[0.25,0.0,0.25,0.75,1.5,0.3125],[0.25,0.0,0.6875,0.75,1.5,0.75],[0.3125,0.0,0.0,0.6875,1.5,0.25],[0.3125,0.0,0.75,0.6875,1.5,1.0]],
"142":[[0.25,0.0,0.25,0.75,1.5,0.75],[0.3125,0.0,0.0,0.6875,1.5,0.25],[0.3125,0.0,0.75,0.6875,1.5,1.0]],
"143":[[0.0,0.0,0.3125,0.6875,1.5,0.6875],[0.3125,0.0,0.0,0.6875,1.5,0.3125],[0.3125,0.0,0.6875,0.6875,1.5,1.0]],
"144":[[0.3125,0.0,0.0,0.6875,1.5,1.0]],
"145":[[0.0,0.0,0.3125,0.75,1.5,0.6875],[0.25,0.0,0.25,0.75,1.5,0.3125],[0.25,0.0,0.6875,0.75,1.5,0.75],[0.3125,0.0,0.0,0.6875,1.5,0.25]],
"146":[[0.25,0.0,0.25,0.75,1.5,0.75],[0.3125,0.0,0.0,0.6875,1.5,0.25]],
"147":[[0.0,0.0,0.3125,0.6875,1.5,0.6875],[0.3125,0.0,0.0,0.6875,1.5,0.3125]],
"148":[[0.3125,0.0,0.0,0.6875,1.5,0.6875]],
"149":[[0.0,0.0,0.3125,0.75,1.5,0.6875],[0.25,0.0,0.25,0.75,1.5,0.3125],[0.25,0.0,0.6875,0.75,1.5,0.75],[0.3125,0.0,0.75,0.6875,1.5,1.0]],
"150":[[0.25,0.0,0.25,0.75,1.5,0.75],[0.3125,0.0,0.75,0.6875,1.5,1.0]],
"151":[[0.0,0.0,0.3125,0.6875,1.5,0.6875],[0.3125,0.0,0.6875,0.6875,1.5,1.0]],
"152":[[0.3125,0.0,0.3125,0.6875,1.5,1.0]],
"153":[[0.0,0.0,0.3125,0.75,1.5,0.6875],[0.25,0.0,0.25,0.75,1.5,0.3125],[0.25,0.0,0.6875,0.75,1.5,0.75]],
"154":[[0.0,0.0,0.3125,0.6875,1.5,0.6875]],
"155":[[0.5,0.0,0.5,0.5,1.5,0.5]],
"156":[[0.3125,0.0,0.3125,0.6875,0.375,0.6875]],
"157":[[0.25,0.0,0.25,0.75,0.5,0.75]],
"158":[[0.25,0.25,0.5,0.75,0.75,1.0]],
"159":[[0.25,0.25,0.0,0.75,0.75,0.5]],
"160":[[0.5,0.25,0.25,1.0,0.75,0.75]],
"161":[[0.0,0.25,0.25,0.5,0.75,0.75]],
"162":[[0.125,0.0,0.125,0.875,0.25,0.875],[0.1875,0.625,0.0,0.8125,1.0,1.0],[0.25,0.25,0.1875,0.75,0.3125,0.8125],[0.375,0.3125,0.25,0.625,0.625,0.75]],
"163":[[0.0,0.625,0.1875,1.0,1.0,0.8125],[0.125,0.0,0.125,0.875,0.25,0.875],[0.1875,0.25,0.25,0.8125,0.3125,0.75],[0.25,0.3125,0.375,0.75,0.625,0.625]],
"164":[[0.0,0.625,0.0,1.0,0.6875,1.0],[0.0,0.6875,0.0,0.125,1.0,1.0],[0.125,0.6875,0.0,1.0,1.0,0.125],[0.125,0.6875,0.875,1.0,1.0,1.0],[0.25,0.25,0.25,0.75,0.625,0.75],[0.375,0.0,0.375,0.625,0.25,0.625],[0.875,0.6875,0.125,1.0,1.0,0.875]],
"165":[[0.0,0.625,0.0,1.0,0.6875,1.0],[0.0,0.6875,0.0,0.125,1.0,1.0],[0.125,0.6875,0.0,1.0,1.0,0.125],[0.125,0.6875,0.875,1.0,1.0,1.0],[0.25,0.25,0.25,0.75,0.625,0.75],[0.375,0.25,0.0,0.625,0.5,0.25],[0.875,0.6875,0.125,1.0,1.0,0.875]],
"166":[[0.0,0.625,0.0,1.0,0.6875,1.0],[0.0,0.6875,0.0,0.125,1.0,1.0],[0.125,0.6875,0.0,1.0,1.0,0.125],[0.125,0.6875,0.875,1.0,1.0,1.0],[0.25,0.25,0.25,0.75,0.625,0.75],[0.375,0.25,0.75,0.625,0.5,1.0],[0.875,0.6875,0.125,1.0,1.0,0.875]],
"167":[[0.0,0.25,0.375,0.75,0.5,0.625],[0.0,0.625,0.0,1.0,0.6875,1.0],[0.0,0.6875,0.0,0.125,1.0,1.0],[0.125,0.6875,0.0,1.0,1.0,0.125],[0.125,0.6875,0.875,1.0,1.0,1.0],[0.25,0.25,0.25,0.75,0.625,0.375],[0.25,0.25,0.625,0.75,0.625,0.75],[0.25,0.5,0.375,0.75,0.625,0.625],[0.875,0.6875,0.125,1.0,1.0,0.875]],
"168":[[0.0,0.625,0.0,1.0,0.6875,1.0],[0.0,0.6875,0.0,0.125,1.0,1.0],[0.125,0.6875,0.0,1.0,1.0,0.125],[0.125,0.6875,0.875,1.0,1.0,1.0],[0.25,0.25,0.25,0.75,0.625,0.75],[0.75,0.25,0.375,1.0,0.5,0.625],[0.875,0.6875,0.125,1.0,1.0,0.875]],
"169":[[0.0,0.5,0.0,1.0,1.0,1.0]],
"170":[[0.0,0.0,0.0,1.0,0.0625,1.0]],
"171":[[0.375,0.0,0.375,0.625,1.0,0.625]],
"172":[[0.375,0.375,0.0,0.625,0.625,1.0]],
"173":[[0.0,0.375,0.375,1.0,0.625,0.625]],
"174":[[0.1875,0.1875,0.1875,0.8125,0.8125,0.8125]],
"175":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"176":[[0.1875,0.0,0.1875,0.8125,1.0,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"177":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"178":[[0.1875,0.0,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"179":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"180":[[0.1875,0.0,0.1875,0.8125,1.0,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"181":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875]],
"182":[[0.1875,0.0,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"183":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"184":[[0.1875,0.0,0.1875,0.8125,1.0,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"185":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"186":[[0.1875,0.0,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"187":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"188":[[0.1875,0.0,0.1875,0.8125,1.0,0.8125],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"189":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125]],
"190":[[0.1875,0.0,0.1875,0.8125,0.8125,0.8125],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"191":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"192":[[0.1875,0.0,0.1875,0.8125,1.0,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"193":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"194":[[0.1875,0.0,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"195":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"196":[[0.1875,0.0,0.1875,0.8125,1.0,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875]],
"197":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875]],
"198":[[0.1875,0.0,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875]],
"199":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"200":[[0.1875,0.0,0.1875,0.8125,1.0,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"201":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"202":[[0.1875,0.0,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"203":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"204":[[0.1875,0.0,0.1875,0.8125,1.0,0.8125]],
"205":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.0,0.1875,0.8125,0.1875,0.8125]],
"206":[[0.1875,0.0,0.1875,0.8125,0.8125,0.8125]],
"207":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"208":[[0.1875,0.1875,0.0,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"209":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"210":[[0.1875,0.1875,0.0,0.8125,0.8125,1.0],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"211":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"212":[[0.1875,0.1875,0.0,0.8125,0.8125,0.8125],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"213":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875]],
"214":[[0.1875,0.1875,0.0,0.8125,0.8125,0.8125],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"215":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"216":[[0.1875,0.1875,0.1875,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"217":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"218":[[0.1875,0.1875,0.1875,0.8125,0.8125,1.0],[0.8125,0.1875,0.1875,1.0,0.8125,0.8125]],
"219":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"220":[[0.1875,0.1875,0.1875,1.0,0.8125,0.8125],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"221":[[0.0,0.1875,0.1875,1.0,0.8125,0.8125]],
"222":[[0.1875,0.1875,0.1875,1.0,0.8125,0.8125]],
"223":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"224":[[0.1875,0.1875,0.0,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"225":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"226":[[0.1875,0.1875,0.0,0.8125,0.8125,1.0]],
"227":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"228":[[0.1875,0.1875,0.0,0.8125,0.8125,0.8125],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"229":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.0,0.8125,0.8125,0.1875]],
"230":[[0.1875,0.1875,0.0,0.8125,0.8125,0.8125]],
"231":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"232":[[0.1875,0.1875,0.1875,0.8125,0.8125,1.0],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"233":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.1875,0.8125,0.8125,0.8125,1.0]],
"234":[[0.1875,0.1875,0.1875,0.8125,0.8125,1.0]],
"235":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125],[0.1875,0.8125,0.1875,0.8125,1.0,0.8125]],
"236":[[0.1875,0.1875,0.1875,0.8125,1.0,0.8125]],
"237":[[0.0,0.1875,0.1875,0.8125,0.8125,0.8125]],
"238":[[0.1875,0.0,0.1875,0.75,0.4375,0.75]],
"239":[[0.0625,0.0,0.0625,0.9375,0.4375,0.9375]],
"240":[[0.375,0.0,0.375,0.625,0.375,0.625]],
"241":[[0.1875,0.0,0.1875,0.8125,0.375,0.8125]],
"242":[[0.125,0.0,0.125,0.875,0.375,0.875]],
"243":[[0.125,0.0,0.125,0.875,0.4375,0.875]],
"244":[[0.3125,0.3125,0.3125,0.6875,0.6875,0.6875]],
"245":[[0.15625,0.0,0.15625,0.34375,1.0,0.34375]],
"246":[[0.0,0.0,0.0,0.125,1.0,0.125],[0.0,0.0,0.875,0.125,1.0,1.0],[0.0,0.875,0.125,1.0,1.0,0.875],[0.125,0.875,0.0,1.0,1.0,0.125],[0.125,0.875,0.875,1.0,1.0,1.0],[0.875,0.0,0.0,1.0,0.875,0.125],[0.875,0.0,0.875,1.0,0.875,1.0]],
"247":[[0.125,0.3125,0.1875,0.875,0.6875,0.5625],[0.125,0.375,0.5625,0.25,0.625,1.0],[0.25,0.125,0.0,0.75,0.3125,0.75],[0.25,0.3125,0.0,0.75,0.875,0.1875],[0.25,0.3125,0.5625,0.75,0.875,0.75],[0.25,0.6875,0.1875,0.75,0.875,0.5625],[0.75,0.375,0.5625,0.875,0.625,1.0]],
"248":[[0.125,0.0,0.375,0.25,0.8125,0.625],[0.125,0.4375,0.3125,0.875,0.8125,0.375],[0.125,0.4375,0.625,0.875,0.8125,0.6875],[0.25,0.25,0.125,0.75,0.4375,0.875],[0.25,0.4375,0.125,0.75,1.0,0.3125],[0.25,0.4375,0.375,0.875,0.8125,0.625],[0.25,0.4375,0.6875,0.75,1.0,0.875],[0.25,0.8125,0.3125,0.75,1.0,0.6875],[0.75,0.0,0.375,0.875,0.4375,0.625]],
"249":[[0.125,0.25,0.25,0.875,1.0,0.75],[0.3125,0.4375,0.125,0.6875,0.8125,0.25],[0.3125,0.4375,0.75,0.6875,0.8125,0.875],[0.375,0.0,0.125,0.625,0.4375,0.25],[0.375,0.0,0.75,0.625,0.4375,0.875]],
"250":[[0.125,0.3125,0.4375,0.875,0.6875,0.8125],[0.125,0.375,0.0,0.25,0.625,0.4375],[0.25,0.125,0.25,0.75,0.3125,1.0],[0.25,0.3125,0.25,0.75,0.875,0.4375],[0.25,0.3125,0.8125,0.75,0.875,1.0],[0.25,0.6875,0.4375,0.75,0.875,0.8125],[0.75,0.375,0.0,0.875,0.625,0.4375]],
"251":[[0.0,0.125,0.25,0.75,0.875,0.75],[0.1875,0.3125,0.125,0.5625,0.6875,0.25],[0.1875,0.3125,0.75,0.5625,0.6875,0.875],[0.5625,0.375,0.125,1.0,0.625,0.25],[0.5625,0.375,0.75,1.0,0.625,0.875]],
"252":[[0.0,0.375,0.125,0.8125,0.625,0.25],[0.0,0.375,0.75,0.8125,0.625,0.875],[0.25,0.125,0.25,1.0,0.875,0.75],[0.4375,0.3125,0.125,0.8125,0.375,0.25],[0.4375,0.3125,0.75,0.8125,0.375,0.875],[0.4375,0.625,0.125,0.8125,0.6875,0.25],[0.4375,0.625,0.75,0.8125,0.6875,0.875]],
"253":[[0.125,0.1875,0.3125,0.875,0.5625,0.6875],[0.125,0.5625,0.375,0.875,0.75,0.625],[0.125,0.75,0.375,0.25,1.0,0.625],[0.25,0.0,0.125,0.75,0.1875,0.875],[0.25,0.1875,0.125,0.75,0.75,0.3125],[0.25,0.1875,0.6875,0.75,0.75,0.875],[0.25,0.5625,0.3125,0.75,0.75,0.375],[0.25,0.5625,0.625,0.75,0.75,0.6875],[0.75,0.75,0.375,0.875,1.0,0.625]],
"254":[[0.125,0.0,0.25,0.875,0.75,0.75],[0.3125,0.1875,0.125,0.6875,0.5625,0.25],[0.3125,0.1875,0.75,0.6875,0.5625,0.875],[0.375,0.5625,0.125,0.625,1.0,0.25],[0.375,0.5625,0.75,0.625,1.0,0.875]],
"255":[[0.0,0.0,0.0,1.0,0.125,1.0],[0.25,0.125,0.25,0.75,0.875,0.75]],
"256":[[0.0,0.0,0.0,1.0,0.5625,1.0]],
"257":[[0.0,0.0,0.25,1.0,1.0,0.75]],
"258":[[0.25,0.0,0.0,0.75,1.0,1.0]],
"259":[[0.25,0.25,0.25,0.75,0.375,0.75],[0.3125,0.375,0.3125,0.6875,0.8125,0.6875],[0.4375,0.8125,0.4375,0.5625,1.0,0.5625]],
"260":[[0.25,0.25,0.25,0.75,0.375,0.75],[0.3125,0.375,0.3125,0.6875,0.8125,0.6875],[0.4375,0.8125,0.0,0.5625,0.9375,0.8125]],
"261":[[0.25,0.25,0.25,0.75,0.375,0.75],[0.3125,0.375,0.3125,0.6875,0.8125,0.6875],[0.4375,0.8125,0.1875,0.5625,0.9375,1.0]],
"262":[[0.0,0.8125,0.4375,0.8125,0.9375,0.5625],[0.25,0.25,0.25,0.75,0.375,0.75],[0.3125,0.375,0.3125,0.6875,0.8125,0.6875]],
"263":[[0.1875,0.8125,0.4375,1.0,0.9375,0.5625],[0.25,0.25,0.25,0.75,0.375,0.75],[0.3125,0.375,0.3125,0.6875,0.8125,0.6875]],
"264":[[0.25,0.25,0.25,0.75,0.375,0.75],[0.3125,0.375,0.3125,0.6875,0.8125,0.6875],[0.4375,0.8125,0.0,0.5625,0.9375,1.0]],
"265":[[0.0,0.8125,0.4375,1.0,0.9375,0.5625],[0.25,0.25,0.25,0.75,0.375,0.75],[0.3125,0.375,0.3125,0.6875,0.8125,0.6875]],
"266":[[0.3125,0.0,0.3125,0.6875,0.4375,0.6875],[0.375,0.4375,0.375,0.625,0.5625,0.625]],
"267":[[0.3125,0.0625,0.3125,0.6875,0.5,0.6875],[0.375,0.5,0.375,0.625,0.625,0.625]],
"268":[[0.0,0.0,0.0,1.0,0.4375,1.0]],
"269":[[0.0,0.0,0.0,1.0,0.125,1.0],[0.0,0.125,0.0,0.125,1.0,1.0],[0.125,0.125,0.0,1.0,1.0,0.125],[0.125,0.125,0.875,1.0,1.0,1.0],[0.875,0.125,0.125,1.0,1.0,0.875]]}}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,200 @@
[
{
"id": 1,
"name": "Speed",
"displayName": "Speed",
"type": "good"
},
{
"id": 2,
"name": "Slowness",
"displayName": "Slowness",
"type": "bad"
},
{
"id": 3,
"name": "Haste",
"displayName": "Haste",
"type": "good"
},
{
"id": 4,
"name": "MiningFatigue",
"displayName": "Mining Fatigue",
"type": "bad"
},
{
"id": 5,
"name": "Strength",
"displayName": "Strength",
"type": "good"
},
{
"id": 6,
"name": "InstantHealth",
"displayName": "Instant Health",
"type": "good"
},
{
"id": 7,
"name": "InstantDamage",
"displayName": "Instant Damage",
"type": "bad"
},
{
"id": 8,
"name": "JumpBoost",
"displayName": "Jump Boost",
"type": "good"
},
{
"id": 9,
"name": "Nausea",
"displayName": "Nausea",
"type": "bad"
},
{
"id": 10,
"name": "Regeneration",
"displayName": "Regeneration",
"type": "good"
},
{
"id": 11,
"name": "Resistance",
"displayName": "Resistance",
"type": "good"
},
{
"id": 12,
"name": "FireResistance",
"displayName": "Fire Resistance",
"type": "good"
},
{
"id": 13,
"name": "WaterBreathing",
"displayName": "Water Breathing",
"type": "good"
},
{
"id": 14,
"name": "Invisibility",
"displayName": "Invisibility",
"type": "good"
},
{
"id": 15,
"name": "Blindness",
"displayName": "Blindness",
"type": "bad"
},
{
"id": 16,
"name": "NightVision",
"displayName": "Night Vision",
"type": "good"
},
{
"id": 17,
"name": "Hunger",
"displayName": "Hunger",
"type": "bad"
},
{
"id": 18,
"name": "Weakness",
"displayName": "Weakness",
"type": "bad"
},
{
"id": 19,
"name": "Poison",
"displayName": "Poison",
"type": "bad"
},
{
"id": 20,
"name": "Wither",
"displayName": "Wither",
"type": "bad"
},
{
"id": 21,
"name": "HealthBoost",
"displayName": "Health Boost",
"type": "good"
},
{
"id": 22,
"name": "Absorption",
"displayName": "Absorption",
"type": "good"
},
{
"id": 23,
"name": "Saturation",
"displayName": "Saturation",
"type": "good"
},
{
"id": 24,
"name": "Glowing",
"displayName": "Glowing",
"type": "bad"
},
{
"id": 25,
"name": "Levitation",
"displayName": "Levitation",
"type": "bad"
},
{
"id": 26,
"name": "Luck",
"displayName": "Luck",
"type": "good"
},
{
"id": 27,
"name": "BadLuck",
"displayName": "Bad Luck",
"type": "bad"
},
{
"id": 28,
"name": "SlowFalling",
"displayName": "Slow Falling",
"type": "good"
},
{
"id": 29,
"name": "ConduitPower",
"displayName": "Conduit Power",
"type": "good"
},
{
"id": 30,
"name": "DolphinsGrace",
"displayName": "Dolphin's Grace",
"type": "good"
},
{
"id": 31,
"name": "DolphinsGrace",
"displayName": "Dolphin's Grace",
"type": "good"
},
{
"id": 32,
"name": "BadOmen",
"displayName": "Bad Omen",
"type": "good"
},
{
"id": 32,
"name": "HeroOfTheVillage",
"displayName": "Hero Of The Village",
"type": "good"
}
]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+392
View File
@@ -0,0 +1,392 @@
[
{
"id": 524,
"displayName": "Apple",
"name": "apple",
"stackSize": 64,
"foodPoints": 4,
"saturation": 2.4,
"effectiveQuality": 6.4,
"saturationRatio": 0.6
},
{
"id": 547,
"displayName": "Mushroom Stew",
"name": "mushroom_stew",
"stackSize": 1,
"foodPoints": 6,
"saturation": 7.2,
"effectiveQuality": 13.2,
"saturationRatio": 1.2
},
{
"id": 562,
"displayName": "Bread",
"name": "bread",
"stackSize": 64,
"foodPoints": 5,
"saturation": 6,
"effectiveQuality": 11,
"saturationRatio": 1.2
},
{
"id": 584,
"displayName": "Raw Porkchop",
"name": "porkchop",
"stackSize": 64,
"foodPoints": 3,
"saturation": 1.8,
"effectiveQuality": 4.8,
"saturationRatio": 0.6
},
{
"id": 585,
"displayName": "Cooked Porkchop",
"name": "cooked_porkchop",
"stackSize": 64,
"foodPoints": 8,
"saturation": 12.8,
"effectiveQuality": 20.8,
"saturationRatio": 1.6
},
{
"id": 587,
"displayName": "Golden Apple",
"name": "golden_apple",
"stackSize": 64,
"foodPoints": 4,
"saturation": 9.6,
"effectiveQuality": 13.6,
"saturationRatio": 2.4
},
{
"id": 588,
"displayName": "Enchanted Golden Apple",
"name": "enchanted_golden_apple",
"stackSize": 64,
"foodPoints": 4,
"saturation": 9.6,
"effectiveQuality": 13.6,
"saturationRatio": 2.4
},
{
"id": 625,
"displayName": "Raw Cod",
"name": "cod",
"stackSize": 64,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
},
{
"id": 626,
"displayName": "Raw Salmon",
"name": "salmon",
"stackSize": 64,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
},
{
"id": 627,
"displayName": "Tropical Fish",
"name": "tropical_fish",
"stackSize": 64,
"foodPoints": 1,
"saturation": 0.2,
"effectiveQuality": 1.2,
"saturationRatio": 0.2
},
{
"id": 628,
"displayName": "Pufferfish",
"name": "pufferfish",
"stackSize": 64,
"foodPoints": 1,
"saturation": 0.2,
"effectiveQuality": 1.2,
"saturationRatio": 0.2
},
{
"id": 629,
"displayName": "Cooked Cod",
"name": "cooked_cod",
"stackSize": 64,
"foodPoints": 5,
"saturation": 6,
"effectiveQuality": 11,
"saturationRatio": 1.2
},
{
"id": 630,
"displayName": "Cooked Salmon",
"name": "cooked_salmon",
"stackSize": 64,
"foodPoints": 6,
"saturation": 9.6,
"effectiveQuality": 15.6,
"saturationRatio": 1.5999999999999999
},
{
"id": 653,
"displayName": "Cake",
"name": "cake",
"stackSize": 1,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
},
{
"id": 670,
"displayName": "Cookie",
"name": "cookie",
"stackSize": 64,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
},
{
"id": 673,
"displayName": "Melon Slice",
"name": "melon_slice",
"stackSize": 64,
"foodPoints": 2,
"saturation": 1.2,
"effectiveQuality": 3.2,
"saturationRatio": 0.6
},
{
"id": 674,
"displayName": "Dried Kelp",
"name": "dried_kelp",
"stackSize": 64,
"foodPoints": 1,
"saturation": 0.6,
"effectiveQuality": 1.6,
"saturationRatio": 0.6
},
{
"id": 677,
"displayName": "Raw Beef",
"name": "beef",
"stackSize": 64,
"foodPoints": 3,
"saturation": 1.8,
"effectiveQuality": 4.8,
"saturationRatio": 0.6
},
{
"id": 678,
"displayName": "Steak",
"name": "cooked_beef",
"stackSize": 64,
"foodPoints": 8,
"saturation": 12.8,
"effectiveQuality": 20.8,
"saturationRatio": 1.6
},
{
"id": 679,
"displayName": "Raw Chicken",
"name": "chicken",
"stackSize": 64,
"foodPoints": 2,
"saturation": 1.2,
"effectiveQuality": 3.2,
"saturationRatio": 0.6
},
{
"id": 680,
"displayName": "Cooked Chicken",
"name": "cooked_chicken",
"stackSize": 64,
"foodPoints": 6,
"saturation": 7.2,
"effectiveQuality": 13.2,
"saturationRatio": 1.2
},
{
"id": 681,
"displayName": "Rotten Flesh",
"name": "rotten_flesh",
"stackSize": 64,
"foodPoints": 4,
"saturation": 0.8,
"effectiveQuality": 4.8,
"saturationRatio": 0.2
},
{
"id": 689,
"displayName": "Spider Eye",
"name": "spider_eye",
"stackSize": 64,
"foodPoints": 2,
"saturation": 3.2,
"effectiveQuality": 5.2,
"saturationRatio": 1.6
},
{
"id": 762,
"displayName": "Carrot",
"name": "carrot",
"stackSize": 64,
"foodPoints": 3,
"saturation": 3.6,
"effectiveQuality": 6.6,
"saturationRatio": 1.2
},
{
"id": 763,
"displayName": "Potato",
"name": "potato",
"stackSize": 64,
"foodPoints": 1,
"saturation": 0.6,
"effectiveQuality": 1.6,
"saturationRatio": 0.6
},
{
"id": 764,
"displayName": "Baked Potato",
"name": "baked_potato",
"stackSize": 64,
"foodPoints": 5,
"saturation": 6,
"effectiveQuality": 11,
"saturationRatio": 1.2
},
{
"id": 765,
"displayName": "Poisonous Potato",
"name": "poisonous_potato",
"stackSize": 64,
"foodPoints": 2,
"saturation": 1.2,
"effectiveQuality": 3.2,
"saturationRatio": 0.6
},
{
"id": 767,
"displayName": "Golden Carrot",
"name": "golden_carrot",
"stackSize": 64,
"foodPoints": 6,
"saturation": 14.4,
"effectiveQuality": 20.4,
"saturationRatio": 2.4
},
{
"id": 776,
"displayName": "Pumpkin Pie",
"name": "pumpkin_pie",
"stackSize": 64,
"foodPoints": 8,
"saturation": 4.8,
"effectiveQuality": 12.8,
"saturationRatio": 0.6
},
{
"id": 786,
"displayName": "Raw Rabbit",
"name": "rabbit",
"stackSize": 64,
"foodPoints": 3,
"saturation": 1.8,
"effectiveQuality": 4.8,
"saturationRatio": 0.6
},
{
"id": 787,
"displayName": "Cooked Rabbit",
"name": "cooked_rabbit",
"stackSize": 64,
"foodPoints": 5,
"saturation": 6,
"effectiveQuality": 11,
"saturationRatio": 1.2
},
{
"id": 788,
"displayName": "Rabbit Stew",
"name": "rabbit_stew",
"stackSize": 1,
"foodPoints": 10,
"saturation": 12,
"effectiveQuality": 22,
"saturationRatio": 1.2
},
{
"id": 799,
"displayName": "Raw Mutton",
"name": "mutton",
"stackSize": 64,
"foodPoints": 2,
"saturation": 1.2,
"effectiveQuality": 3.2,
"saturationRatio": 0.6
},
{
"id": 800,
"displayName": "Cooked Mutton",
"name": "cooked_mutton",
"stackSize": 64,
"foodPoints": 6,
"saturation": 9.6,
"effectiveQuality": 15.6,
"saturationRatio": 1.5999999999999999
},
{
"id": 818,
"displayName": "Chorus Fruit",
"name": "chorus_fruit",
"stackSize": 64,
"foodPoints": 4,
"saturation": 2.4,
"effectiveQuality": 6.4,
"saturationRatio": 0.6
},
{
"id": 820,
"displayName": "Beetroot",
"name": "beetroot",
"stackSize": 64,
"foodPoints": 1,
"saturation": 1.2,
"effectiveQuality": 2.2,
"saturationRatio": 1.2
},
{
"id": 822,
"displayName": "Beetroot Soup",
"name": "beetroot_soup",
"stackSize": 1,
"foodPoints": 6,
"saturation": 7.2,
"effectiveQuality": 13.2,
"saturationRatio": 1.2
},
{
"id": 857,
"displayName": "Suspicious Stew",
"name": "suspicious_stew",
"stackSize": 1,
"foodPoints": 6,
"saturation": 7.2,
"effectiveQuality": 13.2,
"saturationRatio": 1.2
},
{
"id": 875,
"displayName": "Sweet Berries",
"name": "sweet_berries",
"stackSize": 64,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
}
]
@@ -0,0 +1,42 @@
[
{
"id": 0,
"name": "harp"
},
{
"id": 1,
"name": "basedrum"
},
{
"id": 2,
"name": "snare"
},
{
"id": 3,
"name": "hat"
},
{
"id": 4,
"name": "bass"
},
{
"id": 5,
"name": "flute"
},
{
"id": 6,
"name": "bell"
},
{
"id": 7,
"name": "guitar"
},
{
"id": 8,
"name": "chime"
},
{
"id": 9,
"name": "xylophone"
}
]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,61 @@
{
"rock": {
"521": 6,
"535": 2,
"539": 4,
"543": 8,
"550": 12
},
"wood": {
"522": 6,
"536": 2,
"540": 4,
"544": 8,
"551": 12
},
"plant": {
"522": 6,
"532": 1.5,
"533": 1.5,
"536": 2,
"537": 1.5,
"540": 4,
"541": 1.5,
"544": 8,
"548": 1.5,
"551": 12
},
"melon": {
"532": 1.5,
"533": 1.5,
"537": 1.5,
"541": 1.5,
"548": 1.5
},
"leaves": {
"532": 1.5,
"533": 1.5,
"537": 1.5,
"541": 1.5,
"548": 1.5,
"672": 6
},
"dirt": {
"520": 6,
"534": 2,
"538": 4,
"542": 8,
"549": 12
},
"web": {
"532": 15,
"533": 15,
"537": 15,
"541": 15,
"548": 15,
"672": 15
},
"wool": {
"672": 4.8
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,5 @@
{
"minecraftVersion": "1.14.4",
"version": 498,
"majorVersion": "1.14"
}
@@ -0,0 +1,229 @@
[
{
"id": "",
"name": "Player",
"slots": [
{
"name": "craft result",
"index": 0
},
{
"name": "craft grid",
"index": 1,
"size": 4
},
{
"name": "armor",
"index": 5,
"size": 4
},
{
"name": "helmet",
"index": 5
},
{
"name": "chestplate",
"index": 6
},
{
"name": "leggings",
"index": 7
},
{
"name": "boots",
"index": 8
}
]
},
{
"id": "EntityHorse",
"name": "Horse",
"slots": [
{
"name": "saddle",
"index": 0
},
{
"name": "armor",
"index": 1
},
{
"name": "storage",
"index": 2,
"size": 15
}
],
"openedWith": [
{
"type": "entity",
"id": 100
}
]
},
{
"id": "minecraft:anvil",
"name": "Anvil",
"slots": [
{
"name": "tool",
"index": 0
},
{
"name": "combined",
"index": 1
},
{
"name": "result",
"index": 2
}
],
"properties": [
"repair cost"
]
},
{
"id": "minecraft:beacon",
"name": "Beacon",
"slots": [
{
"name": "input",
"index": 0
}
],
"properties": [
"level",
"effect 1",
"effect 2"
],
"openedWith": [
{
"type": "block",
"id": 138
}
]
},
{
"id": "minecraft:brewing_stand",
"name": "Brewing Stand",
"slots": [
{
"name": "ingredient",
"index": 0
},
{
"name": "result",
"index": 1,
"size": 3
}
],
"properties": [
"brew time"
],
"openedWith": [
{
"type": "block",
"id": 117
}
]
},
{
"id": "minecraft:chest",
"name": "Chest"
},
{
"id": "minecraft:container",
"name": "Container"
},
{
"id": "minecraft:crafting_table",
"name": "Workbench",
"slots": [
{
"name": "craft result",
"index": 0
},
{
"name": "craft grid",
"index": 1,
"size": 9
}
]
},
{
"id": "minecraft:dispenser",
"name": "Dispenser"
},
{
"id": "minecraft:dropper",
"name": "Dropper"
},
{
"id": "minecraft:enchanting_table",
"name": "Enchantment Table",
"slots": [
{
"name": "enchanted",
"index": 0
},
{
"name": "lapis",
"index": 1
}
],
"properties": [
"xp 1",
"xp 2",
"xp 3",
"seed",
"tooltip 1",
"tooltip 2",
"tooltip 3"
]
},
{
"id": "minecraft:furnace",
"name": "Furnace",
"slots": [
{
"name": "smelted",
"index": 0
},
{
"name": "fuel",
"index": 1
},
{
"name": "result",
"index": 2
}
],
"properties": [
"fuel",
"fuel max",
"progress",
"progress max"
]
},
{
"id": "minecraft:hopper",
"name": "Hopper"
},
{
"id": "minecraft:villager",
"name": "NPC Trade",
"slots": [
{
"name": "give 1",
"index": 0
},
{
"name": "give 2",
"index": 1
},
{
"name": "take",
"index": 2
}
]
}
]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,200 @@
[
{
"id": 1,
"name": "Speed",
"displayName": "Speed",
"type": "good"
},
{
"id": 2,
"name": "Slowness",
"displayName": "Slowness",
"type": "bad"
},
{
"id": 3,
"name": "Haste",
"displayName": "Haste",
"type": "good"
},
{
"id": 4,
"name": "MiningFatigue",
"displayName": "Mining Fatigue",
"type": "bad"
},
{
"id": 5,
"name": "Strength",
"displayName": "Strength",
"type": "good"
},
{
"id": 6,
"name": "InstantHealth",
"displayName": "Instant Health",
"type": "good"
},
{
"id": 7,
"name": "InstantDamage",
"displayName": "Instant Damage",
"type": "bad"
},
{
"id": 8,
"name": "JumpBoost",
"displayName": "Jump Boost",
"type": "good"
},
{
"id": 9,
"name": "Nausea",
"displayName": "Nausea",
"type": "bad"
},
{
"id": 10,
"name": "Regeneration",
"displayName": "Regeneration",
"type": "good"
},
{
"id": 11,
"name": "Resistance",
"displayName": "Resistance",
"type": "good"
},
{
"id": 12,
"name": "FireResistance",
"displayName": "Fire Resistance",
"type": "good"
},
{
"id": 13,
"name": "WaterBreathing",
"displayName": "Water Breathing",
"type": "good"
},
{
"id": 14,
"name": "Invisibility",
"displayName": "Invisibility",
"type": "good"
},
{
"id": 15,
"name": "Blindness",
"displayName": "Blindness",
"type": "bad"
},
{
"id": 16,
"name": "NightVision",
"displayName": "Night Vision",
"type": "good"
},
{
"id": 17,
"name": "Hunger",
"displayName": "Hunger",
"type": "bad"
},
{
"id": 18,
"name": "Weakness",
"displayName": "Weakness",
"type": "bad"
},
{
"id": 19,
"name": "Poison",
"displayName": "Poison",
"type": "bad"
},
{
"id": 20,
"name": "Wither",
"displayName": "Wither",
"type": "bad"
},
{
"id": 21,
"name": "HealthBoost",
"displayName": "Health Boost",
"type": "good"
},
{
"id": 22,
"name": "Absorption",
"displayName": "Absorption",
"type": "good"
},
{
"id": 23,
"name": "Saturation",
"displayName": "Saturation",
"type": "good"
},
{
"id": 24,
"name": "Glowing",
"displayName": "Glowing",
"type": "bad"
},
{
"id": 25,
"name": "Levitation",
"displayName": "Levitation",
"type": "bad"
},
{
"id": 26,
"name": "Luck",
"displayName": "Luck",
"type": "good"
},
{
"id": 27,
"name": "BadLuck",
"displayName": "Bad Luck",
"type": "bad"
},
{
"id": 28,
"name": "SlowFalling",
"displayName": "Slow Falling",
"type": "good"
},
{
"id": 29,
"name": "ConduitPower",
"displayName": "Conduit Power",
"type": "good"
},
{
"id": 30,
"name": "DolphinsGrace",
"displayName": "Dolphin's Grace",
"type": "good"
},
{
"id": 31,
"name": "DolphinsGrace",
"displayName": "Dolphin's Grace",
"type": "good"
},
{
"id": 32,
"name": "BadOmen",
"displayName": "Bad Omen",
"type": "good"
},
{
"id": 32,
"name": "HeroOfTheVillage",
"displayName": "Hero Of The Village",
"type": "good"
}
]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+402
View File
@@ -0,0 +1,402 @@
[
{
"id": 576,
"displayName": "Apple",
"name": "apple",
"stackSize": 64,
"foodPoints": 4,
"saturation": 2.4,
"effectiveQuality": 6.4,
"saturationRatio": 0.6
},
{
"id": 601,
"displayName": "Mushroom Stew",
"name": "mushroom_stew",
"stackSize": 1,
"foodPoints": 6,
"saturation": 7.2,
"effectiveQuality": 13.2,
"saturationRatio": 1.2
},
{
"id": 621,
"displayName": "Bread",
"name": "bread",
"stackSize": 64,
"foodPoints": 5,
"saturation": 6,
"effectiveQuality": 11,
"saturationRatio": 1.2
},
{
"id": 647,
"displayName": "Raw Porkchop",
"name": "porkchop",
"stackSize": 64,
"foodPoints": 3,
"saturation": 1.8,
"effectiveQuality": 4.8,
"saturationRatio": 0.6
},
{
"id": 648,
"displayName": "Cooked Porkchop",
"name": "cooked_porkchop",
"stackSize": 64,
"foodPoints": 8,
"saturation": 12.8,
"effectiveQuality": 20.8,
"saturationRatio": 1.6
},
{
"id": 650,
"displayName": "Golden Apple",
"name": "golden_apple",
"stackSize": 64,
"foodPoints": 4,
"saturation": 9.6,
"effectiveQuality": 13.6,
"saturationRatio": 2.4
},
{
"id": 651,
"displayName": "Enchanted Golden Apple",
"name": "enchanted_golden_apple",
"stackSize": 64,
"foodPoints": 4,
"saturation": 9.6,
"effectiveQuality": 13.6,
"saturationRatio": 2.4
},
{
"id": 687,
"displayName": "Raw Cod",
"name": "cod",
"stackSize": 64,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
},
{
"id": 688,
"displayName": "Raw Salmon",
"name": "salmon",
"stackSize": 64,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
},
{
"id": 689,
"displayName": "Tropical Fish",
"name": "tropical_fish",
"stackSize": 64,
"foodPoints": 1,
"saturation": 0.2,
"effectiveQuality": 1.2,
"saturationRatio": 0.2
},
{
"id": 690,
"displayName": "Pufferfish",
"name": "pufferfish",
"stackSize": 64,
"foodPoints": 1,
"saturation": 0.2,
"effectiveQuality": 1.2,
"saturationRatio": 0.2
},
{
"id": 691,
"displayName": "Cooked Cod",
"name": "cooked_cod",
"stackSize": 64,
"foodPoints": 5,
"saturation": 6,
"effectiveQuality": 11,
"saturationRatio": 1.2
},
{
"id": 692,
"displayName": "Cooked Salmon",
"name": "cooked_salmon",
"stackSize": 64,
"foodPoints": 6,
"saturation": 9.6,
"effectiveQuality": 15.6,
"saturationRatio": 1.5999999999999999
},
{
"id": 715,
"displayName": "Cake",
"name": "cake",
"stackSize": 1,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
},
{
"id": 732,
"displayName": "Cookie",
"name": "cookie",
"stackSize": 64,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
},
{
"id": 735,
"displayName": "Melon Slice",
"name": "melon_slice",
"stackSize": 64,
"foodPoints": 2,
"saturation": 1.2,
"effectiveQuality": 3.2,
"saturationRatio": 0.6
},
{
"id": 736,
"displayName": "Dried Kelp",
"name": "dried_kelp",
"stackSize": 64,
"foodPoints": 1,
"saturation": 0.6,
"effectiveQuality": 1.6,
"saturationRatio": 0.6
},
{
"id": 739,
"displayName": "Raw Beef",
"name": "beef",
"stackSize": 64,
"foodPoints": 3,
"saturation": 1.8,
"effectiveQuality": 4.8,
"saturationRatio": 0.6
},
{
"id": 740,
"displayName": "Steak",
"name": "cooked_beef",
"stackSize": 64,
"foodPoints": 8,
"saturation": 12.8,
"effectiveQuality": 20.8,
"saturationRatio": 1.6
},
{
"id": 741,
"displayName": "Raw Chicken",
"name": "chicken",
"stackSize": 64,
"foodPoints": 2,
"saturation": 1.2,
"effectiveQuality": 3.2,
"saturationRatio": 0.6
},
{
"id": 742,
"displayName": "Cooked Chicken",
"name": "cooked_chicken",
"stackSize": 64,
"foodPoints": 6,
"saturation": 7.2,
"effectiveQuality": 13.2,
"saturationRatio": 1.2
},
{
"id": 743,
"displayName": "Rotten Flesh",
"name": "rotten_flesh",
"stackSize": 64,
"foodPoints": 4,
"saturation": 0.8,
"effectiveQuality": 4.8,
"saturationRatio": 0.2
},
{
"id": 751,
"displayName": "Spider Eye",
"name": "spider_eye",
"stackSize": 64,
"foodPoints": 2,
"saturation": 3.2,
"effectiveQuality": 5.2,
"saturationRatio": 1.6
},
{
"id": 829,
"displayName": "Carrot",
"name": "carrot",
"stackSize": 64,
"foodPoints": 3,
"saturation": 3.6,
"effectiveQuality": 6.6,
"saturationRatio": 1.2
},
{
"id": 830,
"displayName": "Potato",
"name": "potato",
"stackSize": 64,
"foodPoints": 1,
"saturation": 0.6,
"effectiveQuality": 1.6,
"saturationRatio": 0.6
},
{
"id": 831,
"displayName": "Baked Potato",
"name": "baked_potato",
"stackSize": 64,
"foodPoints": 5,
"saturation": 6,
"effectiveQuality": 11,
"saturationRatio": 1.2
},
{
"id": 832,
"displayName": "Poisonous Potato",
"name": "poisonous_potato",
"stackSize": 64,
"foodPoints": 2,
"saturation": 1.2,
"effectiveQuality": 3.2,
"saturationRatio": 0.6
},
{
"id": 834,
"displayName": "Golden Carrot",
"name": "golden_carrot",
"stackSize": 64,
"foodPoints": 6,
"saturation": 14.4,
"effectiveQuality": 20.4,
"saturationRatio": 2.4
},
{
"id": 844,
"displayName": "Pumpkin Pie",
"name": "pumpkin_pie",
"stackSize": 64,
"foodPoints": 8,
"saturation": 4.8,
"effectiveQuality": 12.8,
"saturationRatio": 0.6
},
{
"id": 854,
"displayName": "Raw Rabbit",
"name": "rabbit",
"stackSize": 64,
"foodPoints": 3,
"saturation": 1.8,
"effectiveQuality": 4.8,
"saturationRatio": 0.6
},
{
"id": 855,
"displayName": "Cooked Rabbit",
"name": "cooked_rabbit",
"stackSize": 64,
"foodPoints": 5,
"saturation": 6,
"effectiveQuality": 11,
"saturationRatio": 1.2
},
{
"id": 856,
"displayName": "Rabbit Stew",
"name": "rabbit_stew",
"stackSize": 1,
"foodPoints": 10,
"saturation": 12,
"effectiveQuality": 22,
"saturationRatio": 1.2
},
{
"id": 867,
"displayName": "Raw Mutton",
"name": "mutton",
"stackSize": 64,
"foodPoints": 2,
"saturation": 1.2,
"effectiveQuality": 3.2,
"saturationRatio": 0.6
},
{
"id": 868,
"displayName": "Cooked Mutton",
"name": "cooked_mutton",
"stackSize": 64,
"foodPoints": 6,
"saturation": 9.6,
"effectiveQuality": 15.6,
"saturationRatio": 1.5999999999999999
},
{
"id": 886,
"displayName": "Chorus Fruit",
"name": "chorus_fruit",
"stackSize": 64,
"foodPoints": 4,
"saturation": 2.4,
"effectiveQuality": 6.4,
"saturationRatio": 0.6
},
{
"id": 888,
"displayName": "Beetroot",
"name": "beetroot",
"stackSize": 64,
"foodPoints": 1,
"saturation": 1.2,
"effectiveQuality": 2.2,
"saturationRatio": 1.2
},
{
"id": 890,
"displayName": "Beetroot Soup",
"name": "beetroot_soup",
"stackSize": 1,
"foodPoints": 6,
"saturation": 7.2,
"effectiveQuality": 13.2,
"saturationRatio": 1.2
},
{
"id": 926,
"displayName": "Suspicious Stew",
"name": "suspicious_stew",
"stackSize": 1,
"foodPoints": 6,
"saturation": 7.2,
"effectiveQuality": 13.2,
"saturationRatio": 1.2
},
{
"id": 947,
"displayName": "Sweet Berries",
"name": "sweet_berries",
"stackSize": 64,
"foodPoints": 2,
"saturation": 0.4,
"effectiveQuality": 2.4,
"saturationRatio": 0.2
},
{
"id": 954,
"displayName": "Honey Bottle",
"name": "honey_bottle",
"stackSize": 16,
"foodPoints": 6,
"saturation": 1.2,
"effectiveQuality": 7.2,
"saturationRatio": 0.19999999999999998
}
]
@@ -0,0 +1,66 @@
[
{
"id": 0,
"name": "harp"
},
{
"id": 1,
"name": "basedrum"
},
{
"id": 2,
"name": "snare"
},
{
"id": 3,
"name": "hat"
},
{
"id": 4,
"name": "bass"
},
{
"id": 5,
"name": "flute"
},
{
"id": 6,
"name": "bell"
},
{
"id": 7,
"name": "guitar"
},
{
"id": 8,
"name": "chime"
},
{
"id": 9,
"name": "xylophone"
},
{
"id": 10,
"name": "iron_xylophone"
},
{
"id": 11,
"name": "cow_bell"
},
{
"id": 12,
"name": "didgeridoo"
},
{
"id": 13,
"name": "bit"
},
{
"id": 14,
"name": "banjo"
},
{
"id": 15,
"name": "pling"
}
]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,69 @@
{
"rock": {
"573": 6,
"589": 2,
"593": 4,
"597": 8,
"608": 9,
"604": 12
},
"wood": {
"574": 6,
"590": 2,
"594": 4,
"598": 8,
"609": 9,
"605": 12
},
"plant": {
"574": 6,
"586": 1.5,
"587": 1.5,
"590": 2,
"591": 1.5,
"594": 4,
"595": 1.5,
"598": 8,
"609": 9,
"606": 1.5,
"602": 1.5,
"605": 12
},
"melon": {
"586": 1.5,
"587": 1.5,
"591": 1.5,
"595": 1.5,
"606": 1.5,
"602": 1.5
},
"leaves": {
"586": 1.5,
"587": 1.5,
"591": 1.5,
"595": 1.5,
"602": 1.5,
"606": 1.5,
"734": 6
},
"dirt": {
"572": 6,
"588": 2,
"592": 4,
"596": 8,
"607": 9,
"603": 12
},
"web": {
"586": 15,
"587": 15,
"591": 15,
"595": 15,
"602": 15,
"606": 15,
"734": 15
},
"wool": {
"734": 4.8
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,5 @@
{
"minecraftVersion": "1.16.1",
"version": 736,
"majorVersion": "1.16"
}
@@ -0,0 +1,229 @@
[
{
"id": "",
"name": "Player",
"slots": [
{
"name": "craft result",
"index": 0
},
{
"name": "craft grid",
"index": 1,
"size": 4
},
{
"name": "armor",
"index": 5,
"size": 4
},
{
"name": "helmet",
"index": 5
},
{
"name": "chestplate",
"index": 6
},
{
"name": "leggings",
"index": 7
},
{
"name": "boots",
"index": 8
}
]
},
{
"id": "EntityHorse",
"name": "Horse",
"slots": [
{
"name": "saddle",
"index": 0
},
{
"name": "armor",
"index": 1
},
{
"name": "storage",
"index": 2,
"size": 15
}
],
"openedWith": [
{
"type": "entity",
"id": 100
}
]
},
{
"id": "minecraft:anvil",
"name": "Anvil",
"slots": [
{
"name": "tool",
"index": 0
},
{
"name": "combined",
"index": 1
},
{
"name": "result",
"index": 2
}
],
"properties": [
"repair cost"
]
},
{
"id": "minecraft:beacon",
"name": "Beacon",
"slots": [
{
"name": "input",
"index": 0
}
],
"properties": [
"level",
"effect 1",
"effect 2"
],
"openedWith": [
{
"type": "block",
"id": 138
}
]
},
{
"id": "minecraft:brewing_stand",
"name": "Brewing Stand",
"slots": [
{
"name": "ingredient",
"index": 0
},
{
"name": "result",
"index": 1,
"size": 3
}
],
"properties": [
"brew time"
],
"openedWith": [
{
"type": "block",
"id": 117
}
]
},
{
"id": "minecraft:chest",
"name": "Chest"
},
{
"id": "minecraft:container",
"name": "Container"
},
{
"id": "minecraft:crafting_table",
"name": "Workbench",
"slots": [
{
"name": "craft result",
"index": 0
},
{
"name": "craft grid",
"index": 1,
"size": 9
}
]
},
{
"id": "minecraft:dispenser",
"name": "Dispenser"
},
{
"id": "minecraft:dropper",
"name": "Dropper"
},
{
"id": "minecraft:enchanting_table",
"name": "Enchantment Table",
"slots": [
{
"name": "enchanted",
"index": 0
},
{
"name": "lapis",
"index": 1
}
],
"properties": [
"xp 1",
"xp 2",
"xp 3",
"seed",
"tooltip 1",
"tooltip 2",
"tooltip 3"
]
},
{
"id": "minecraft:furnace",
"name": "Furnace",
"slots": [
{
"name": "smelted",
"index": 0
},
{
"name": "fuel",
"index": 1
},
{
"name": "result",
"index": 2
}
],
"properties": [
"fuel",
"fuel max",
"progress",
"progress max"
]
},
{
"id": "minecraft:hopper",
"name": "Hopper"
},
{
"id": "minecraft:villager",
"name": "NPC Trade",
"slots": [
{
"name": "give 1",
"index": 0
},
{
"name": "give 2",
"index": 1
},
{
"name": "take",
"index": 2
}
]
}
]
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More