From a5e6acea73c6b81f5b0d704ab81ac2d50618a7d7 Mon Sep 17 00:00:00 2001 From: Tnze Date: Sun, 19 Nov 2023 10:06:53 +0800 Subject: [PATCH 1/2] update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index de29dd1..e3ed01a 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![Discord](https://img.shields.io/discord/915805561138860063?label=Discord)](https://discord.gg/A4qh8BT8Ue) ### [教程 · Tutorial](https://go-mc.github.io/tutorial/) +### [文档 · Documents](https://pkg.go.dev/github.com/Tnze/go-mc) Require Go version: 1.20 From 54ffcb2badbdbb89e67a1bb1305bbbf2cff9158f Mon Sep 17 00:00:00 2001 From: Tnze Date: Sun, 19 Nov 2023 11:25:17 +0800 Subject: [PATCH 2/2] add configuration support for /server packet --- bot/client.go | 10 +- examples/simpleServer1.15.2/main.go | 175 -- examples/simpleServer1.15.2/status.go | 67 - examples/simpleServer1.17.1/Dimension.snbt | 17 - .../simpleServer1.17.1/DimensionCodec.snbt | 2028 ----------------- examples/simpleServer1.17.1/main.go | 186 -- examples/simpleServer1.17.1/status.go | 66 - examples/sniffRegistryCodec/daze.go | 91 - examples/yggdrasil/launcher.go | 33 - server/configuration.go | 39 + server/login.go | 9 + server/server.go | 19 +- 12 files changed, 72 insertions(+), 2668 deletions(-) delete mode 100644 examples/simpleServer1.15.2/main.go delete mode 100644 examples/simpleServer1.15.2/status.go delete mode 100644 examples/simpleServer1.17.1/Dimension.snbt delete mode 100644 examples/simpleServer1.17.1/DimensionCodec.snbt delete mode 100644 examples/simpleServer1.17.1/main.go delete mode 100644 examples/simpleServer1.17.1/status.go delete mode 100644 examples/sniffRegistryCodec/daze.go delete mode 100644 examples/yggdrasil/launcher.go create mode 100644 server/configuration.go diff --git a/bot/client.go b/bot/client.go index 373532b..26074d6 100644 --- a/bot/client.go +++ b/bot/client.go @@ -17,12 +17,16 @@ type Client struct { Conn *Conn Auth Auth + // These are filled when login process + Name string UUID uuid.UUID - - Events Events - LoginPlugin map[string]func(data []byte) ([]byte, error) ConfigData + + // Ingame packet handlers + Events Events + // Login plugins + LoginPlugin map[string]func(data []byte) ([]byte, error) } func (c *Client) Close() error { diff --git a/examples/simpleServer1.15.2/main.go b/examples/simpleServer1.15.2/main.go deleted file mode 100644 index b1ac20e..0000000 --- a/examples/simpleServer1.15.2/main.go +++ /dev/null @@ -1,175 +0,0 @@ -// This example is a minimal minecraft 1.15.2 server allowing vanilla clients or go-mc/bot to connect. -// -// This example handles "ping and list", so you can see its motd and player count in server list. -// Players can join the server and seeing an empty world. No authentication profile is checked. -// The KeepAlive packet is not handled, so client might exit 20 seconds later. -// -// It doesn't use go-mc/server but the go-mc/net package to handle the connection and implement basic 1.15.2 protocol, -// proving that even latest go-mc also support old minecraft versions. -package main - -import ( - "log" - - "github.com/google/uuid" - - "github.com/Tnze/go-mc/net" - pk "github.com/Tnze/go-mc/net/packet" - "github.com/Tnze/go-mc/offline" -) - -const ( - ProtocolVersion = 578 - MaxPlayer = 200 -) - -// Packet IDs -const ( - PlayerPositionAndLookClientbound = 0x36 - JoinGame = 0x26 -) - -func main() { - l, err := net.ListenMC(":25565") - if err != nil { - log.Fatalf("Listen error: %v", err) - } - - for { - conn, err := l.Accept() - if err != nil { - log.Fatalf("Accept error: %v", err) - } - go acceptConn(conn) - } -} - -func acceptConn(conn net.Conn) { - defer conn.Close() - // handshake - protocol, intention, err := handshake(conn) - if err != nil { - log.Printf("Handshake error: %v", err) - return - } - - switch intention { - default: // unknown error - log.Printf("Unknown handshake intention: %v", intention) - case 1: // for status - acceptListPing(conn) - case 2: // for login - handlePlaying(conn, protocol) - } -} - -func handlePlaying(conn net.Conn, protocol int32) { - // login, get player info - info, err := acceptLogin(conn) - if err != nil { - log.Print("Login failed") - return - } - - // Write LoginSuccess packet - - if err = loginSuccess(conn, info.Name, info.UUID); err != nil { - log.Print("Login failed on success") - return - } - - if err := joinGame(conn); err != nil { - log.Print("Login failed on joinGame") - return - } - if err := conn.WritePacket(pk.Marshal(PlayerPositionAndLookClientbound, - // https://wiki.vg/index.php?title=Protocol&oldid=16067#Player_Position_And_Look_.28clientbound.29 - pk.Double(0), pk.Double(0), pk.Double(0), // XYZ - pk.Float(0), pk.Float(0), // Yaw Pitch - pk.Byte(0), // flag - pk.VarInt(0), // TP ID - )); err != nil { - log.Print("Login failed on sending PlayerPositionAndLookClientbound") - return - } - // Just for block this goroutine. Keep the connection - for { - var p pk.Packet - if err := conn.ReadPacket(&p); err != nil { - log.Printf("ReadPacket error: %v", err) - break - } - // KeepAlive packet is not handled, so client might - // exit because of "time out". - } -} - -type PlayerInfo struct { - Name string - UUID uuid.UUID - OPLevel int -} - -// acceptLogin check player's account -func acceptLogin(conn net.Conn) (info PlayerInfo, err error) { - // login start - var p pk.Packet - err = conn.ReadPacket(&p) - if err != nil { - return - } - - err = p.Scan((*pk.String)(&info.Name)) // decode username as pk.String - if err != nil { - return - } - - // auth - const OnlineMode = false - if OnlineMode { - log.Panic("Not Implement") - } else { - // offline-mode UUID - info.UUID = offline.NameToUUID(info.Name) - } - - return -} - -// handshake receive and parse Handshake packet -func handshake(conn net.Conn) (protocol, intention int32, err error) { - var ( - p pk.Packet - Protocol, Intention pk.VarInt - ServerAddress pk.String // ignored - ServerPort pk.UnsignedShort // ignored - ) - // receive handshake packet - if err = conn.ReadPacket(&p); err != nil { - return - } - err = p.Scan(&Protocol, &ServerAddress, &ServerPort, &Intention) - return int32(Protocol), int32(Intention), err -} - -// loginSuccess send LoginSuccess packet to client -func loginSuccess(conn net.Conn, name string, uuid uuid.UUID) error { - return conn.WritePacket(pk.Marshal(0x02, - pk.String(uuid.String()), // uuid as string with hyphens - pk.String(name), - )) -} - -func joinGame(conn net.Conn) error { - return conn.WritePacket(pk.Marshal(JoinGame, - pk.Int(0), // EntityID - pk.UnsignedByte(1), // Gamemode - pk.Int(0), // Dimension - pk.Long(0), // HashedSeed - pk.UnsignedByte(MaxPlayer), // MaxPlayer - pk.String("default"), // LevelType - pk.VarInt(15), // View Distance - pk.Boolean(false), // Reduced Debug Info - pk.Boolean(true), // Enable respawn screen - )) -} diff --git a/examples/simpleServer1.15.2/status.go b/examples/simpleServer1.15.2/status.go deleted file mode 100644 index 72103c4..0000000 --- a/examples/simpleServer1.15.2/status.go +++ /dev/null @@ -1,67 +0,0 @@ -package main - -import ( - "encoding/json" - "log" - - "github.com/google/uuid" - - "github.com/Tnze/go-mc/chat" - "github.com/Tnze/go-mc/net" - pk "github.com/Tnze/go-mc/net/packet" -) - -func acceptListPing(conn net.Conn) { - var p pk.Packet - for i := 0; i < 2; i++ { // ping or list. Only accept twice - err := conn.ReadPacket(&p) - if err != nil { - return - } - - switch p.ID { - case 0x00: // List - err = conn.WritePacket(pk.Marshal(0x00, pk.String(listResp()))) - case 0x01: // Ping - err = conn.WritePacket(p) - } - if err != nil { - return - } - } -} - -type player struct { - Name string `json:"name"` - ID uuid.UUID `json:"id"` -} - -// listResp return server status as JSON string -func listResp() string { - var list struct { - Version struct { - Name string `json:"name"` - Protocol int `json:"protocol"` - } `json:"version"` - Players struct { - Max int `json:"max"` - Online int `json:"online"` - Sample []player `json:"sample"` - } `json:"players"` - Description chat.Message `json:"description"` - FavIcon string `json:"favicon,omitempty"` - } - - list.Version.Name = "Chat Server" - list.Version.Protocol = ProtocolVersion - list.Players.Max = MaxPlayer - list.Players.Online = 123 - list.Players.Sample = []player{} // must init. can't be nil - list.Description = chat.Message{Text: "Powered by go-mc", Color: "blue"} - - data, err := json.Marshal(list) - if err != nil { - log.Panic("Marshal JSON for status checking fail") - } - return string(data) -} diff --git a/examples/simpleServer1.17.1/Dimension.snbt b/examples/simpleServer1.17.1/Dimension.snbt deleted file mode 100644 index 2b9092d..0000000 --- a/examples/simpleServer1.17.1/Dimension.snbt +++ /dev/null @@ -1,17 +0,0 @@ -{ - piglin_safe: 0b, - natural: 1b, - ambient_light: 0.0f, - infiniburn: "minecraft:infiniburn_overworld", - respawn_anchor_works: 0b, - has_skylight: 1b, - bed_works: 1b, - effects: "minecraft:overworld", - has_raids: 1b, - min_y: 0, - height: 256, - logical_height: 256, - coordinate_scale: 1.0d, - ultrawarm: 0b, - has_ceiling: 0b -} \ No newline at end of file diff --git a/examples/simpleServer1.17.1/DimensionCodec.snbt b/examples/simpleServer1.17.1/DimensionCodec.snbt deleted file mode 100644 index 44ea6d5..0000000 --- a/examples/simpleServer1.17.1/DimensionCodec.snbt +++ /dev/null @@ -1,2028 +0,0 @@ -{ - "minecraft:dimension_type": { - type: "minecraft:dimension_type", - value: [ - { - name: "minecraft:overworld", - id: 0, - element: { - piglin_safe: 0b, - natural: 1b, - ambient_light: 0.0f, - infiniburn: "minecraft:infiniburn_overworld", - respawn_anchor_works: 0b, - has_skylight: 1b, - bed_works: 1b, - effects: "minecraft:overworld", - has_raids: 1b, - min_y: 0, - height: 256, - logical_height: 256, - coordinate_scale: 1.0d, - ultrawarm: 0b, - has_ceiling: 0b - } - } - ] - }, - "minecraft:worldgen/biome": { - type: "minecraft:worldgen/biome", - value: [ - { - name: "minecraft:ocean", - id: 0, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.0f, - temperature: 0.5f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean" - } - }, - { - name: "minecraft:plains", - id: 1, - element: { - precipitation: "rain", - effects: { - sky_color: 7907327, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.125f, - temperature: 0.8f, - scale: 0.05f, - downfall: 0.4f, - category: "plains" - } - }, - { - name: "minecraft:desert", - id: 2, - element: { - precipitation: "none", - effects: { - sky_color: 7254527, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.125f, - temperature: 2.0f, - scale: 0.05f, - downfall: 0.0f, - category: "desert" - } - }, - { - name: "minecraft:mountains", - id: 3, - element: { - precipitation: "rain", - effects: { - sky_color: 8233727, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 1.0f, - temperature: 0.2f, - scale: 0.5f, - downfall: 0.3f, - category: "extreme_hills" - } - }, - { - name: "minecraft:forest", - id: 4, - element: { - precipitation: "rain", - effects: { - sky_color: 7972607, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.7f, - scale: 0.2f, - downfall: 0.8f, - category: "forest" - } - }, - { - name: "minecraft:taiga", - id: 5, - element: { - precipitation: "rain", - effects: { - sky_color: 8233983, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: 0.25f, - scale: 0.2f, - downfall: 0.8f, - category: "taiga" - } - }, - { - name: "minecraft:swamp", - id: 6, - element: { - precipitation: "rain", - effects: { - grass_color_modifier: "swamp", - sky_color: 7907327, - foliage_color: 6975545, - water_fog_color: 2302743, - fog_color: 12638463, - water_color: 6388580, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -0.2f, - temperature: 0.8f, - scale: 0.1f, - downfall: 0.9f, - category: "swamp" - } - }, - { - name: "minecraft:river", - id: 7, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -0.5f, - temperature: 0.5f, - scale: 0.0f, - downfall: 0.5f, - category: "river" - } - }, - { - name: "minecraft:nether_wastes", - id: 8, - element: { - precipitation: "none", - effects: { - music: { - replace_current_music: 0b, - max_delay: 24000, - sound: "minecraft:music.nether.nether_wastes", - min_delay: 12000 - }, - sky_color: 7254527, - ambient_sound: "minecraft:ambient.nether_wastes.loop", - additions_sound: { - sound: "minecraft:ambient.nether_wastes.additions", - tick_chance: 0.0111d - }, - water_fog_color: 329011, - fog_color: 3344392, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.nether_wastes.mood", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 2.0f, - scale: 0.2f, - downfall: 0.0f, - category: "nether" - } - }, - { - name: "minecraft:the_end", - id: 9, - element: { - precipitation: "none", - effects: { - sky_color: 0, - water_fog_color: 329011, - fog_color: 10518688, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.5f, - scale: 0.2f, - downfall: 0.5f, - category: "the_end" - } - }, - { - name: "minecraft:frozen_ocean", - id: 10, - element: { - precipitation: "snow", - effects: { - sky_color: 8364543, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 3750089, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.0f, - temperature: 0.0f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean", - temperature_modifier: "frozen" - } - }, - { - name: "minecraft:frozen_river", - id: 11, - element: { - precipitation: "snow", - effects: { - sky_color: 8364543, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 3750089, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -0.5f, - temperature: 0.0f, - scale: 0.0f, - downfall: 0.5f, - category: "river" - } - }, - { - name: "minecraft:snowy_tundra", - id: 12, - element: { - precipitation: "snow", - effects: { - sky_color: 8364543, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.125f, - temperature: 0.0f, - scale: 0.05f, - downfall: 0.5f, - category: "icy" - } - }, - { - name: "minecraft:snowy_mountains", - id: 13, - element: { - precipitation: "snow", - effects: { - sky_color: 8364543, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 0.0f, - scale: 0.3f, - downfall: 0.5f, - category: "icy" - } - }, - { - name: "minecraft:mushroom_fields", - id: 14, - element: { - precipitation: "rain", - effects: { - sky_color: 7842047, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: 0.9f, - scale: 0.3f, - downfall: 1.0f, - category: "mushroom" - } - }, - { - name: "minecraft:mushroom_field_shore", - id: 15, - element: { - precipitation: "rain", - effects: { - sky_color: 7842047, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.0f, - temperature: 0.9f, - scale: 0.025f, - downfall: 1.0f, - category: "mushroom" - } - }, - { - name: "minecraft:beach", - id: 16, - element: { - precipitation: "rain", - effects: { - sky_color: 7907327, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.0f, - temperature: 0.8f, - scale: 0.025f, - downfall: 0.4f, - category: "beach" - } - }, - { - name: "minecraft:desert_hills", - id: 17, - element: { - precipitation: "none", - effects: { - sky_color: 7254527, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 2.0f, - scale: 0.3f, - downfall: 0.0f, - category: "desert" - } - }, - { - name: "minecraft:wooded_hills", - id: 18, - element: { - precipitation: "rain", - effects: { - sky_color: 7972607, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 0.7f, - scale: 0.3f, - downfall: 0.8f, - category: "forest" - } - }, - { - name: "minecraft:taiga_hills", - id: 19, - element: { - precipitation: "rain", - effects: { - sky_color: 8233983, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 0.25f, - scale: 0.3f, - downfall: 0.8f, - category: "taiga" - } - }, - { - name: "minecraft:mountain_edge", - id: 20, - element: { - precipitation: "rain", - effects: { - sky_color: 8233727, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.8f, - temperature: 0.2f, - scale: 0.3f, - downfall: 0.3f, - category: "extreme_hills" - } - }, - { - name: "minecraft:jungle", - id: 21, - element: { - precipitation: "rain", - effects: { - sky_color: 7842047, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.95f, - scale: 0.2f, - downfall: 0.9f, - category: "jungle" - } - }, - { - name: "minecraft:jungle_hills", - id: 22, - element: { - precipitation: "rain", - effects: { - sky_color: 7842047, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 0.95f, - scale: 0.3f, - downfall: 0.9f, - category: "jungle" - } - }, - { - name: "minecraft:jungle_edge", - id: 23, - element: { - precipitation: "rain", - effects: { - sky_color: 7842047, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.95f, - scale: 0.2f, - downfall: 0.8f, - category: "jungle" - } - }, - { - name: "minecraft:deep_ocean", - id: 24, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.8f, - temperature: 0.5f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean" - } - }, - { - name: "minecraft:stone_shore", - id: 25, - element: { - precipitation: "rain", - effects: { - sky_color: 8233727, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.2f, - scale: 0.8f, - downfall: 0.3f, - category: "none" - } - }, - { - name: "minecraft:snowy_beach", - id: 26, - element: { - precipitation: "snow", - effects: { - sky_color: 8364543, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4020182, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.0f, - temperature: 0.05f, - scale: 0.025f, - downfall: 0.3f, - category: "beach" - } - }, - { - name: "minecraft:birch_forest", - id: 27, - element: { - precipitation: "rain", - effects: { - sky_color: 8037887, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.6f, - scale: 0.2f, - downfall: 0.6f, - category: "forest" - } - }, - { - name: "minecraft:birch_forest_hills", - id: 28, - element: { - precipitation: "rain", - effects: { - sky_color: 8037887, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 0.6f, - scale: 0.3f, - downfall: 0.6f, - category: "forest" - } - }, - { - name: "minecraft:dark_forest", - id: 29, - element: { - precipitation: "rain", - effects: { - grass_color_modifier: "dark_forest", - sky_color: 7972607, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.7f, - scale: 0.2f, - downfall: 0.8f, - category: "forest" - } - }, - { - name: "minecraft:snowy_taiga", - id: 30, - element: { - precipitation: "snow", - effects: { - sky_color: 8625919, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4020182, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: -0.5f, - scale: 0.2f, - downfall: 0.4f, - category: "taiga" - } - }, - { - name: "minecraft:snowy_taiga_hills", - id: 31, - element: { - precipitation: "snow", - effects: { - sky_color: 8625919, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4020182, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: -0.5f, - scale: 0.3f, - downfall: 0.4f, - category: "taiga" - } - }, - { - name: "minecraft:giant_tree_taiga", - id: 32, - element: { - precipitation: "rain", - effects: { - sky_color: 8168447, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: 0.3f, - scale: 0.2f, - downfall: 0.8f, - category: "taiga" - } - }, - { - name: "minecraft:giant_tree_taiga_hills", - id: 33, - element: { - precipitation: "rain", - effects: { - sky_color: 8168447, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 0.3f, - scale: 0.3f, - downfall: 0.8f, - category: "taiga" - } - }, - { - name: "minecraft:wooded_mountains", - id: 34, - element: { - precipitation: "rain", - effects: { - sky_color: 8233727, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 1.0f, - temperature: 0.2f, - scale: 0.5f, - downfall: 0.3f, - category: "extreme_hills" - } - }, - { - name: "minecraft:savanna", - id: 35, - element: { - precipitation: "none", - effects: { - sky_color: 7711487, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.125f, - temperature: 1.2f, - scale: 0.05f, - downfall: 0.0f, - category: "savanna" - } - }, - { - name: "minecraft:savanna_plateau", - id: 36, - element: { - precipitation: "none", - effects: { - sky_color: 7776511, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 1.5f, - temperature: 1.0f, - scale: 0.025f, - downfall: 0.0f, - category: "savanna" - } - }, - { - name: "minecraft:badlands", - id: 37, - element: { - precipitation: "none", - effects: { - sky_color: 7254527, - grass_color: 9470285, - foliage_color: 10387789, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 2.0f, - scale: 0.2f, - downfall: 0.0f, - category: "mesa" - } - }, - { - name: "minecraft:wooded_badlands_plateau", - id: 38, - element: { - precipitation: "none", - effects: { - sky_color: 7254527, - grass_color: 9470285, - foliage_color: 10387789, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 1.5f, - temperature: 2.0f, - scale: 0.025f, - downfall: 0.0f, - category: "mesa" - } - }, - { - name: "minecraft:badlands_plateau", - id: 39, - element: { - precipitation: "none", - effects: { - sky_color: 7254527, - grass_color: 9470285, - foliage_color: 10387789, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 1.5f, - temperature: 2.0f, - scale: 0.025f, - downfall: 0.0f, - category: "mesa" - } - }, - { - name: "minecraft:small_end_islands", - id: 40, - element: { - precipitation: "none", - effects: { - sky_color: 0, - water_fog_color: 329011, - fog_color: 10518688, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.5f, - scale: 0.2f, - downfall: 0.5f, - category: "the_end" - } - }, - { - name: "minecraft:end_midlands", - id: 41, - element: { - precipitation: "none", - effects: { - sky_color: 0, - water_fog_color: 329011, - fog_color: 10518688, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.5f, - scale: 0.2f, - downfall: 0.5f, - category: "the_end" - } - }, - { - name: "minecraft:end_highlands", - id: 42, - element: { - precipitation: "none", - effects: { - sky_color: 0, - water_fog_color: 329011, - fog_color: 10518688, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.5f, - scale: 0.2f, - downfall: 0.5f, - category: "the_end" - } - }, - { - name: "minecraft:end_barrens", - id: 43, - element: { - precipitation: "none", - effects: { - sky_color: 0, - water_fog_color: 329011, - fog_color: 10518688, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.5f, - scale: 0.2f, - downfall: 0.5f, - category: "the_end" - } - }, - { - name: "minecraft:warm_ocean", - id: 44, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 270131, - fog_color: 12638463, - water_color: 4445678, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.0f, - temperature: 0.5f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean" - } - }, - { - name: "minecraft:lukewarm_ocean", - id: 45, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 267827, - fog_color: 12638463, - water_color: 4566514, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.0f, - temperature: 0.5f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean" - } - }, - { - name: "minecraft:cold_ocean", - id: 46, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4020182, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.0f, - temperature: 0.5f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean" - } - }, - { - name: "minecraft:deep_warm_ocean", - id: 47, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 270131, - fog_color: 12638463, - water_color: 4445678, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.8f, - temperature: 0.5f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean" - } - }, - { - name: "minecraft:deep_lukewarm_ocean", - id: 48, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 267827, - fog_color: 12638463, - water_color: 4566514, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.8f, - temperature: 0.5f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean" - } - }, - { - name: "minecraft:deep_cold_ocean", - id: 49, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4020182, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.8f, - temperature: 0.5f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean" - } - }, - { - name: "minecraft:deep_frozen_ocean", - id: 50, - element: { - precipitation: "rain", - effects: { - sky_color: 8103167, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 3750089, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -1.8f, - temperature: 0.5f, - scale: 0.1f, - downfall: 0.5f, - category: "ocean", - temperature_modifier: "frozen" - } - }, - { - name: "minecraft:the_void", - id: 127, - element: { - precipitation: "none", - effects: { - sky_color: 8103167, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.5f, - scale: 0.2f, - downfall: 0.5f, - category: "none" - } - }, - { - name: "minecraft:sunflower_plains", - id: 129, - element: { - precipitation: "rain", - effects: { - sky_color: 7907327, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.125f, - temperature: 0.8f, - scale: 0.05f, - downfall: 0.4f, - category: "plains" - } - }, - { - name: "minecraft:desert_lakes", - id: 130, - element: { - precipitation: "none", - effects: { - sky_color: 7254527, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.225f, - temperature: 2.0f, - scale: 0.25f, - downfall: 0.0f, - category: "desert" - } - }, - { - name: "minecraft:gravelly_mountains", - id: 131, - element: { - precipitation: "rain", - effects: { - sky_color: 8233727, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 1.0f, - temperature: 0.2f, - scale: 0.5f, - downfall: 0.3f, - category: "extreme_hills" - } - }, - { - name: "minecraft:flower_forest", - id: 132, - element: { - precipitation: "rain", - effects: { - sky_color: 7972607, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.7f, - scale: 0.4f, - downfall: 0.8f, - category: "forest" - } - }, - { - name: "minecraft:taiga_mountains", - id: 133, - element: { - precipitation: "rain", - effects: { - sky_color: 8233983, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.3f, - temperature: 0.25f, - scale: 0.4f, - downfall: 0.8f, - category: "taiga" - } - }, - { - name: "minecraft:swamp_hills", - id: 134, - element: { - precipitation: "rain", - effects: { - grass_color_modifier: "swamp", - sky_color: 7907327, - foliage_color: 6975545, - water_fog_color: 2302743, - fog_color: 12638463, - water_color: 6388580, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: -0.1f, - temperature: 0.8f, - scale: 0.3f, - downfall: 0.9f, - category: "swamp" - } - }, - { - name: "minecraft:ice_spikes", - id: 140, - element: { - precipitation: "snow", - effects: { - sky_color: 8364543, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.425f, - temperature: 0.0f, - scale: 0.45000002f, - downfall: 0.5f, - category: "icy" - } - }, - { - name: "minecraft:modified_jungle", - id: 149, - element: { - precipitation: "rain", - effects: { - sky_color: 7842047, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: 0.95f, - scale: 0.4f, - downfall: 0.9f, - category: "jungle" - } - }, - { - name: "minecraft:modified_jungle_edge", - id: 151, - element: { - precipitation: "rain", - effects: { - sky_color: 7842047, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: 0.95f, - scale: 0.4f, - downfall: 0.8f, - category: "jungle" - } - }, - { - name: "minecraft:tall_birch_forest", - id: 155, - element: { - precipitation: "rain", - effects: { - sky_color: 8037887, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: 0.6f, - scale: 0.4f, - downfall: 0.6f, - category: "forest" - } - }, - { - name: "minecraft:tall_birch_hills", - id: 156, - element: { - precipitation: "rain", - effects: { - sky_color: 8037887, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.55f, - temperature: 0.6f, - scale: 0.5f, - downfall: 0.6f, - category: "forest" - } - }, - { - name: "minecraft:dark_forest_hills", - id: 157, - element: { - precipitation: "rain", - effects: { - grass_color_modifier: "dark_forest", - sky_color: 7972607, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: 0.7f, - scale: 0.4f, - downfall: 0.8f, - category: "forest" - } - }, - { - name: "minecraft:snowy_taiga_mountains", - id: 158, - element: { - precipitation: "snow", - effects: { - sky_color: 8625919, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4020182, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.3f, - temperature: -0.5f, - scale: 0.4f, - downfall: 0.4f, - category: "taiga" - } - }, - { - name: "minecraft:giant_spruce_taiga", - id: 160, - element: { - precipitation: "rain", - effects: { - sky_color: 8233983, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: 0.25f, - scale: 0.2f, - downfall: 0.8f, - category: "taiga" - } - }, - { - name: "minecraft:giant_spruce_taiga_hills", - id: 161, - element: { - precipitation: "rain", - effects: { - sky_color: 8233983, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.2f, - temperature: 0.25f, - scale: 0.2f, - downfall: 0.8f, - category: "taiga" - } - }, - { - name: "minecraft:modified_gravelly_mountains", - id: 162, - element: { - precipitation: "rain", - effects: { - sky_color: 8233727, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 1.0f, - temperature: 0.2f, - scale: 0.5f, - downfall: 0.3f, - category: "extreme_hills" - } - }, - { - name: "minecraft:shattered_savanna", - id: 163, - element: { - precipitation: "none", - effects: { - sky_color: 7776767, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.3625f, - temperature: 1.1f, - scale: 1.225f, - downfall: 0.0f, - category: "savanna" - } - }, - { - name: "minecraft:shattered_savanna_plateau", - id: 164, - element: { - precipitation: "none", - effects: { - sky_color: 7776511, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 1.05f, - temperature: 1.0f, - scale: 1.2125001f, - downfall: 0.0f, - category: "savanna" - } - }, - { - name: "minecraft:eroded_badlands", - id: 165, - element: { - precipitation: "none", - effects: { - sky_color: 7254527, - grass_color: 9470285, - foliage_color: 10387789, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 2.0f, - scale: 0.2f, - downfall: 0.0f, - category: "mesa" - } - }, - { - name: "minecraft:modified_wooded_badlands_plateau", - id: 166, - element: { - precipitation: "none", - effects: { - sky_color: 7254527, - grass_color: 9470285, - foliage_color: 10387789, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 2.0f, - scale: 0.3f, - downfall: 0.0f, - category: "mesa" - } - }, - { - name: "minecraft:modified_badlands_plateau", - id: 167, - element: { - precipitation: "none", - effects: { - sky_color: 7254527, - grass_color: 9470285, - foliage_color: 10387789, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 2.0f, - scale: 0.3f, - downfall: 0.0f, - category: "mesa" - } - }, - { - name: "minecraft:bamboo_jungle", - id: 168, - element: { - precipitation: "rain", - effects: { - sky_color: 7842047, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 0.95f, - scale: 0.2f, - downfall: 0.9f, - category: "jungle" - } - }, - { - name: "minecraft:bamboo_jungle_hills", - id: 169, - element: { - precipitation: "rain", - effects: { - sky_color: 7842047, - water_fog_color: 329011, - fog_color: 12638463, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.cave", - block_search_extent: 8 - } - }, - depth: 0.45f, - temperature: 0.95f, - scale: 0.3f, - downfall: 0.9f, - category: "jungle" - } - }, - { - name: "minecraft:soul_sand_valley", - id: 170, - element: { - precipitation: "none", - effects: { - music: { - replace_current_music: 0b, - max_delay: 24000, - sound: "minecraft:music.nether.soul_sand_valley", - min_delay: 12000 - }, - sky_color: 7254527, - ambient_sound: "minecraft:ambient.soul_sand_valley.loop", - additions_sound: { - sound: "minecraft:ambient.soul_sand_valley.additions", - tick_chance: 0.0111d - }, - particle: { - probability: 0.00625f, - options: { - type: "minecraft:ash" - } - }, - water_fog_color: 329011, - fog_color: 1787717, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.soul_sand_valley.mood", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 2.0f, - scale: 0.2f, - downfall: 0.0f, - category: "nether" - } - }, - { - name: "minecraft:crimson_forest", - id: 171, - element: { - precipitation: "none", - effects: { - music: { - replace_current_music: 0b, - max_delay: 24000, - sound: "minecraft:music.nether.crimson_forest", - min_delay: 12000 - }, - sky_color: 7254527, - ambient_sound: "minecraft:ambient.crimson_forest.loop", - additions_sound: { - sound: "minecraft:ambient.crimson_forest.additions", - tick_chance: 0.0111d - }, - particle: { - probability: 0.025f, - options: { - type: "minecraft:crimson_spore" - } - }, - water_fog_color: 329011, - fog_color: 3343107, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.crimson_forest.mood", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 2.0f, - scale: 0.2f, - downfall: 0.0f, - category: "nether" - } - }, - { - name: "minecraft:warped_forest", - id: 172, - element: { - precipitation: "none", - effects: { - music: { - replace_current_music: 0b, - max_delay: 24000, - sound: "minecraft:music.nether.warped_forest", - min_delay: 12000 - }, - sky_color: 7254527, - ambient_sound: "minecraft:ambient.warped_forest.loop", - additions_sound: { - sound: "minecraft:ambient.warped_forest.additions", - tick_chance: 0.0111d - }, - particle: { - probability: 0.01428f, - options: { - type: "minecraft:warped_spore" - } - }, - water_fog_color: 329011, - fog_color: 1705242, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.warped_forest.mood", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 2.0f, - scale: 0.2f, - downfall: 0.0f, - category: "nether" - } - }, - { - name: "minecraft:basalt_deltas", - id: 173, - element: { - precipitation: "none", - effects: { - music: { - replace_current_music: 0b, - max_delay: 24000, - sound: "minecraft:music.nether.basalt_deltas", - min_delay: 12000 - }, - sky_color: 7254527, - ambient_sound: "minecraft:ambient.basalt_deltas.loop", - additions_sound: { - sound: "minecraft:ambient.basalt_deltas.additions", - tick_chance: 0.0111d - }, - particle: { - probability: 0.118093334f, - options: { - type: "minecraft:white_ash" - } - }, - water_fog_color: 4341314, - fog_color: 6840176, - water_color: 4159204, - mood_sound: { - tick_delay: 6000, - offset: 2.0d, - sound: "minecraft:ambient.basalt_deltas.mood", - block_search_extent: 8 - } - }, - depth: 0.1f, - temperature: 2.0f, - scale: 0.2f, - downfall: 0.0f, - category: "nether" - } - } - ] - } -} \ No newline at end of file diff --git a/examples/simpleServer1.17.1/main.go b/examples/simpleServer1.17.1/main.go deleted file mode 100644 index a76b6c52..0000000 --- a/examples/simpleServer1.17.1/main.go +++ /dev/null @@ -1,186 +0,0 @@ -// This example is a minimal minecraft 1.17.1 server allowing vanilla clients or go-mc/bot to connect. -// Has the same functionality as "simpleServer1.15.2", but with 1.17.1 protocol. -// -// It is used to test DimensionCodec stuffs during go-mc development. -package main - -import ( - _ "embed" - "log" - - "github.com/google/uuid" - - "github.com/Tnze/go-mc/nbt" - "github.com/Tnze/go-mc/net" - pk "github.com/Tnze/go-mc/net/packet" - "github.com/Tnze/go-mc/offline" -) - -const ( - ProtocolVersion = 756 - MaxPlayer = 200 -) - -// Packet IDs -const ( - PlayerPositionAndLookClientbound = 0x38 - JoinGame = 0x26 -) - -func main() { - l, err := net.ListenMC(":25565") - if err != nil { - log.Fatalf("Listen error: %v", err) - } - - for { - conn, err := l.Accept() - if err != nil { - log.Fatalf("Accept error: %v", err) - } - go acceptConn(conn) - } -} - -func acceptConn(conn net.Conn) { - defer conn.Close() - // handshake - protocol, intention, err := handshake(conn) - if err != nil { - log.Printf("Handshake error: %v", err) - return - } - - switch intention { - default: // unknown error - log.Printf("Unknown handshake intention: %v", intention) - case 1: // for status - acceptListPing(conn) - case 2: // for login - handlePlaying(conn, protocol) - } -} - -func handlePlaying(conn net.Conn, protocol int32) { - // login, get player info - info, err := acceptLogin(conn) - if err != nil { - log.Print("Login failed") - return - } - - // Write LoginSuccess packet - - if err = loginSuccess(conn, info.Name, info.UUID); err != nil { - log.Print("Login failed on success") - return - } - - if err := joinGame(conn); err != nil { - log.Print("Login failed on joinGame") - return - } - if err := conn.WritePacket(pk.Marshal(PlayerPositionAndLookClientbound, - // https://wiki.vg/index.php?title=Protocol&oldid=16067#Player_Position_And_Look_.28clientbound.29 - pk.Double(0), pk.Double(0), pk.Double(0), // XYZ - pk.Float(0), pk.Float(0), // Yaw Pitch - pk.Byte(0), // flag - pk.VarInt(0), // TP ID - pk.Boolean(false), // Dismount vehicle - )); err != nil { - log.Printf("Login failed on sending PlayerPositionAndLookClientbound: %v", err) - return - } - // Just for block this goroutine. Keep the connection - for { - var p pk.Packet - if err := conn.ReadPacket(&p); err != nil { - log.Printf("ReadPacket error: %v", err) - break - } - // KeepAlive packet is not handled, so client might - // exit because of "time out". - } -} - -type PlayerInfo struct { - Name string - UUID uuid.UUID - OPLevel int -} - -// acceptLogin check player's account -func acceptLogin(conn net.Conn) (info PlayerInfo, err error) { - // login start - var p pk.Packet - err = conn.ReadPacket(&p) - if err != nil { - return - } - - err = p.Scan((*pk.String)(&info.Name)) // decode username as pk.String - if err != nil { - return - } - - // auth - const OnlineMode = false - if OnlineMode { - log.Panic("Not Implement") - } else { - // offline-mode UUID - info.UUID = offline.NameToUUID(info.Name) - } - - return -} - -// handshake receive and parse Handshake packet -func handshake(conn net.Conn) (protocol, intention int32, err error) { - var ( - p pk.Packet - Protocol, Intention pk.VarInt - ServerAddress pk.String // ignored - ServerPort pk.UnsignedShort // ignored - ) - // receive handshake packet - if err = conn.ReadPacket(&p); err != nil { - return - } - err = p.Scan(&Protocol, &ServerAddress, &ServerPort, &Intention) - return int32(Protocol), int32(Intention), err -} - -// loginSuccess send LoginSuccess packet to client -func loginSuccess(conn net.Conn, name string, uuid uuid.UUID) error { - return conn.WritePacket(pk.Marshal(0x02, - pk.UUID(uuid), - pk.String(name), - )) -} - -//go:embed DimensionCodec.snbt -var dimensionCodecSNBT string - -//go:embed Dimension.snbt -var dimensionSNBT string - -func joinGame(conn net.Conn) error { - return conn.WritePacket(pk.Marshal(JoinGame, - pk.Int(0), // EntityID - pk.Boolean(false), // Is hardcore - pk.UnsignedByte(1), // Gamemode - pk.Byte(1), // Previous Gamemode - pk.Array([]pk.Identifier{"world"}), // World Names - pk.NBT(nbt.StringifiedMessage(dimensionCodecSNBT)), // Dimension codec - pk.NBT(nbt.StringifiedMessage(dimensionSNBT)), // Dimension - pk.Identifier("world"), // World Name - pk.Long(0), // Hashed Seed - pk.VarInt(MaxPlayer), // Max Players - pk.VarInt(15), // View Distance - pk.Boolean(false), // Reduced Debug Info - pk.Boolean(true), // Enable respawn screen - pk.Boolean(false), // Is Debug - pk.Boolean(true), // Is Flat - )) -} diff --git a/examples/simpleServer1.17.1/status.go b/examples/simpleServer1.17.1/status.go deleted file mode 100644 index e3096cb..0000000 --- a/examples/simpleServer1.17.1/status.go +++ /dev/null @@ -1,66 +0,0 @@ -package main - -import ( - "encoding/json" - "log" - - "github.com/Tnze/go-mc/chat" - "github.com/Tnze/go-mc/net" - pk "github.com/Tnze/go-mc/net/packet" - "github.com/google/uuid" -) - -func acceptListPing(conn net.Conn) { - var p pk.Packet - for i := 0; i < 2; i++ { // ping or list. Only accept twice - err := conn.ReadPacket(&p) - if err != nil { - return - } - - switch p.ID { - case 0x00: // List - err = conn.WritePacket(pk.Marshal(0x00, pk.String(listResp()))) - case 0x01: // Ping - err = conn.WritePacket(p) - } - if err != nil { - return - } - } -} - -type player struct { - Name string `json:"name"` - ID uuid.UUID `json:"id"` -} - -// listResp return server status as JSON string -func listResp() string { - var list struct { - Version struct { - Name string `json:"name"` - Protocol int `json:"protocol"` - } `json:"version"` - Players struct { - Max int `json:"max"` - Online int `json:"online"` - Sample []player `json:"sample"` - } `json:"players"` - Description chat.Message `json:"description"` - FavIcon string `json:"favicon,omitempty"` - } - - list.Version.Name = "Chat Server" - list.Version.Protocol = ProtocolVersion - list.Players.Max = MaxPlayer - list.Players.Online = 123 - list.Players.Sample = []player{} // must init. can't be nil - list.Description = chat.Message{Text: "Powered by go-mc", Color: "blue"} - - data, err := json.Marshal(list) - if err != nil { - log.Panic("Marshal JSON for status checking fail") - } - return string(data) -} diff --git a/examples/sniffRegistryCodec/daze.go b/examples/sniffRegistryCodec/daze.go deleted file mode 100644 index f1048d3..0000000 --- a/examples/sniffRegistryCodec/daze.go +++ /dev/null @@ -1,91 +0,0 @@ -// sniffRegistryCodec is an example that acts as a client, -// connects to the server and saves its RegistryCodec to a .nbt file. -package main - -import ( - "flag" - "log" - "os" - - //"github.com/mattn/go-colorable" - - "github.com/Tnze/go-mc/bot" - "github.com/Tnze/go-mc/bot/basic" - _ "github.com/Tnze/go-mc/data/lang/zh-cn" - "github.com/Tnze/go-mc/data/packetid" - "github.com/Tnze/go-mc/nbt" - pk "github.com/Tnze/go-mc/net/packet" -) - -var ( - address = flag.String("address", "127.0.0.1", "The server address") - client *bot.Client - player *basic.Player -) - -func main() { - flag.Parse() - // log.SetOutput(colorable.NewColorableStdout()) - client = bot.NewClient() - client.Auth.Name = "Daze" - player = basic.NewPlayer(client, basic.DefaultSettings, basic.EventsListener{}) - - // To receive the raw NBT data, create a new packet handler - // instead of just reading player.RegistryCodec in GameStart event. - client.Events.AddListener(bot.PacketHandler{ - ID: packetid.ClientboundLogin, - Priority: 50, - F: onLogin, - }) - - // Login - err := client.JoinServer(*address) - if err != nil { - log.Fatal(err) - } - log.Println("Login success") - - // JoinGame - for { - if err = client.HandleGame(); err == nil { - panic("HandleGame never return nil") - } - log.Fatal(err) - } -} - -func onLogin(p pk.Packet) error { - var DimensionNames []pk.Identifier - var RegistryCodec nbt.RawMessage - err := p.Scan( - new(pk.Int), // Entity ID - new(pk.Boolean), // Is hardcore - new(pk.Byte), // Gamemode - new(pk.Byte), // Previous Gamemode - pk.Array(&DimensionNames), // Dimension Names - pk.NBT(&RegistryCodec), // Registry Codec (Only care about this) - // ...Ignored - ) - if err != nil { - return err - } - err = saveToFile("RegistryCodec.nbt", RegistryCodec) - if err != nil { - return err - } - log.Print("Successfully written RegistryCodec.nbt") - return nil -} - -func saveToFile(filename string, value any) (err error) { - f, err := os.Create(filename) - if err != nil { - return nil - } - defer func(f *os.File) { - if err2 := f.Close(); err == nil { - err = err2 - } - }(f) - return nbt.NewEncoder(f).Encode(value, "") -} diff --git a/examples/yggdrasil/launcher.go b/examples/yggdrasil/launcher.go deleted file mode 100644 index 85f7371..0000000 --- a/examples/yggdrasil/launcher.go +++ /dev/null @@ -1,33 +0,0 @@ -// This example used to act as a launcher, log in and obtain the access token. -// The Yggdrasil Authentication is no longer available. This example doesn't work now. -// -// For now, you should use Microsoft Authentication. The description and example code can be found here: -// https://wiki.vg/Microsoft_Authentication_Scheme -package main - -import ( - "flag" - "fmt" - "os" - - "github.com/Tnze/go-mc/yggdrasil" -) - -var ( - user = flag.String("user", "", "Can be an email address or player name for unmigrated accounts") - pswd = flag.String("password", "", "Your password") -) - -func main() { - flag.Parse() - - resp, err := yggdrasil.Authenticate(*user, *pswd) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - id, name := resp.SelectedProfile() - fmt.Println("user:", name) - fmt.Println("uuid:", id) - fmt.Println("astk:", resp.AccessToken()) -} diff --git a/server/configuration.go b/server/configuration.go new file mode 100644 index 0000000..8aa7f30 --- /dev/null +++ b/server/configuration.go @@ -0,0 +1,39 @@ +package server + +import ( + "github.com/Tnze/go-mc/chat" + "github.com/Tnze/go-mc/data/packetid" + "github.com/Tnze/go-mc/net" + pk "github.com/Tnze/go-mc/net/packet" + "github.com/Tnze/go-mc/registry" +) + +type ConfigHandler interface { + AcceptConfig(conn *net.Conn) error +} + +type Configurations struct { + Registries registry.NetworkCodec +} + +func (c *Configurations) AcceptConfig(conn *net.Conn) error { + err := conn.WritePacket(pk.Marshal( + packetid.ClientboundConfigRegistryData, + pk.NBT(c.Registries), + )) + if err != nil { + return err + } + err = conn.WritePacket(pk.Marshal( + packetid.ClientboundConfigFinishConfiguration, + )) + return err +} + +type ConfigFailErr struct { + reason chat.Message +} + +func (c ConfigFailErr) Error() string { + return "config error: " + c.reason.ClearString() +} diff --git a/server/login.go b/server/login.go index c86c1d9..a38735c 100644 --- a/server/login.go +++ b/server/login.go @@ -157,6 +157,15 @@ func (d *MojangLoginHandler) AcceptLogin(conn *net.Conn, protocol int32) (name s pk.String(name), pk.Array(properties), )) + if err != nil { + return + } + + // receive login ack + err = conn.ReadPacket(&p) + if err == nil && packetid.ServerboundPacketID(p.ID) != packetid.ServerboundLoginAcknowledged { + err = wrongPacketErr{expect: int32(packetid.ServerboundLoginAcknowledged), get: p.ID} + } return } diff --git a/server/server.go b/server/server.go index 7c484b2..345c83f 100644 --- a/server/server.go +++ b/server/server.go @@ -38,14 +38,15 @@ import ( ) const ( - ProtocolName = "1.19.4" - ProtocolVersion = 762 + ProtocolName = "1.20.2" + ProtocolVersion = 764 ) type Server struct { *log.Logger ListPingHandler LoginHandler + ConfigHandler GamePlay } @@ -89,6 +90,20 @@ func (s *Server) AcceptConn(conn *net.Conn) { } return } + s.AcceptConfig(conn) + if err != nil { + var configErr ConfigFailErr + if errors.As(err, &configErr) { + _ = conn.WritePacket(pk.Marshal( + packetid.ClientboundConfigDisconnect, + configErr.reason, + )) + } + if s.Logger != nil { + s.Logger.Printf("client %v config error: %v", conn.Socket.RemoteAddr(), err) + } + return + } s.AcceptPlayer(name, id, profilePubKey, properties, protocol, conn) } }