1.21.111 support

This commit is contained in:
AkmalFairuz
2025-10-02 15:22:28 +07:00
parent 99a7495fc2
commit bb157beb03
21 changed files with 9715 additions and 99 deletions

View File

@@ -21,6 +21,7 @@ var (
// must be set to true if you're using Dragonfly.
func All(dragonflyMapping bool) []minecraft.Protocol {
return []minecraft.Protocol{
New827(dragonflyMapping),
New819(dragonflyMapping),
New818(dragonflyMapping),
New800(dragonflyMapping),

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
package legacypacket
import (
"github.com/akmalfairuz/legacy-version/legacyver/proto"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
// GameRulesChanged is sent by the server to the client to update client-side game rules, such as game rules
// like the 'showCoordinates' game rule.
type GameRulesChanged struct {
// GameRules defines game rules changed with their respective values. The value of these game rules may be
// either 'bool', 'int32' or 'float32'.
// Note that some game rules are server side only, and don't necessarily need to be sent to the client.
// Only changed game rules need to be sent in this packet. Game rules that were not changed do not need to
// be sent if the client is already updated on them.
GameRules []protocol.GameRule
}
// ID ...
func (*GameRulesChanged) ID() uint32 {
return packet.IDGameRulesChanged
}
func (pk *GameRulesChanged) Marshal(io protocol.IO) {
if proto.IsProtoGTE(io, proto.ID844) {
protocol.FuncSlice(io, &pk.GameRules, io.GameRule)
} else {
protocol.FuncSlice(io, &pk.GameRules, io.GameRuleLegacy)
}
}

View File

@@ -1 +0,0 @@
package legacypacket

View File

@@ -9,20 +9,8 @@ import (
// PlayerArmourDamage is sent by the server to damage the armour of a player. It is a very efficient packet,
// but generally it's much easier to just send a slot update for the damaged armour.
type PlayerArmourDamage struct {
// Bitset holds a bitset of 4 bits that indicate which pieces of armour need to have damage dealt to them.
// The first bit, when toggled, is for a helmet, the second for the chestplate, the third for the leggings
// and the fourth for boots.
Bitset uint8
// HelmetDamage is the amount of damage that should be dealt to the helmet.
HelmetDamage int32
// ChestplateDamage is the amount of damage that should be dealt to the chestplate.
ChestplateDamage int32
// LeggingsDamage is the amount of damage that should be dealt to the leggings.
LeggingsDamage int32
// BootsDamage is the amount of damage that should be dealt to the boots.
BootsDamage int32
// BodyDamage is the amount of damage that should be dealt to the body.
BodyDamage int32
// List ...
List []protocol.PlayerArmourDamageEntry
}
// ID ...
@@ -31,33 +19,49 @@ func (pk *PlayerArmourDamage) ID() uint32 {
}
func (pk *PlayerArmourDamage) Marshal(io protocol.IO) {
io.Uint8(&pk.Bitset)
if pk.Bitset&packet.PlayerArmourDamageFlagHelmet != 0 {
io.Varint32(&pk.HelmetDamage)
} else {
pk.HelmetDamage = 0
}
if pk.Bitset&packet.PlayerArmourDamageFlagChestplate != 0 {
io.Varint32(&pk.ChestplateDamage)
} else {
pk.ChestplateDamage = 0
}
if pk.Bitset&packet.PlayerArmourDamageFlagLeggings != 0 {
io.Varint32(&pk.LeggingsDamage)
} else {
pk.LeggingsDamage = 0
}
if pk.Bitset&packet.PlayerArmourDamageFlagBoots != 0 {
io.Varint32(&pk.BootsDamage)
} else {
pk.BootsDamage = 0
}
if proto.IsProtoGTE(io, proto.ID712) {
if pk.Bitset&packet.PlayerArmourDamageFlagBody != 0 {
io.Varint32(&pk.BodyDamage)
} else {
pk.BodyDamage = 0
if proto.IsProtoLT(io, proto.ID844) {
var bitset uint8
flags := []uint8{packet.PlayerArmourDamageFlagHelmet, packet.PlayerArmourDamageFlagChestplate, packet.PlayerArmourDamageFlagLeggings, packet.PlayerArmourDamageFlagBoots}
if proto.IsProtoGTE(io, proto.ID712) {
flags = append(flags, packet.PlayerArmourDamageFlagBody)
}
if proto.IsReader(io) {
io.Uint8(&bitset)
pk.List = make([]protocol.PlayerArmourDamageEntry, 0, len(flags))
for _, flag := range flags {
if bitset&flag != 0 {
v := protocol.PlayerArmourDamageEntry{
ArmourSlot: flag,
}
v2 := int32(0)
io.Varint32(&v2)
v.Damage = int16(v2)
pk.List = append(pk.List, v)
}
}
return
}
for _, entry := range pk.List {
if entry.ArmourSlot == packet.PlayerArmourDamageFlagBody && !proto.IsProtoGTE(io, proto.ID712) {
continue
}
bitset |= 1 << entry.ArmourSlot
}
io.Uint8(&bitset)
for _, flag := range flags {
if bitset&flag != 0 {
damage := int32(0)
for _, entry := range pk.List {
if entry.ArmourSlot == flag {
damage = int32(entry.Damage)
break
}
}
io.Varint32(&damage)
}
}
return
}
protocol.SliceVarint32Length(io, &pk.List)
}

View File

@@ -284,7 +284,7 @@ func (pk *StartGame) Marshal(io protocol.IO) {
io.Varint32(&pk.PlatformBroadcastMode)
io.Bool(&pk.CommandsEnabled)
io.Bool(&pk.TexturePackRequired)
protocol.FuncSlice(io, &pk.GameRules, io.GameRule)
protocol.FuncSlice(io, &pk.GameRules, io.GameRuleLegacy)
protocol.SliceUint32Length(io, &pk.Experiments)
io.Bool(&pk.ExperimentsPreviouslyToggled)
io.Bool(&pk.BonusChestEnabled)

View File

@@ -21,6 +21,8 @@ type BiomeDefinition struct {
AshDensity float32
// WhiteAshDensity is the density of white ash precipitation visuals.
WhiteAshDensity float32
// FoliageSnow ...
FoliageSnow float32
// Depth ...
Depth float32
// Scale ...
@@ -52,10 +54,15 @@ func (x *BiomeDefinition) Marshal(r protocol.IO) {
}
r.Float32(&x.Temperature)
r.Float32(&x.Downfall)
r.Float32(&x.RedSporeDensity)
r.Float32(&x.BlueSporeDensity)
r.Float32(&x.AshDensity)
r.Float32(&x.WhiteAshDensity)
if IsProtoLT(r, ID844) {
r.Float32(&x.RedSporeDensity)
r.Float32(&x.BlueSporeDensity)
r.Float32(&x.AshDensity)
r.Float32(&x.WhiteAshDensity)
}
if IsProtoGTE(r, ID844) {
r.Float32(&x.FoliageSnow)
}
r.Float32(&x.Depth)
r.Float32(&x.Scale)
r.Int32(&x.MapWaterColour)
@@ -71,10 +78,11 @@ func (x *BiomeDefinition) FromLatest(bd protocol.BiomeDefinition) BiomeDefinitio
x.BiomeID = bd.BiomeID
x.Temperature = bd.Temperature
x.Downfall = bd.Downfall
x.RedSporeDensity = bd.RedSporeDensity
x.BlueSporeDensity = bd.BlueSporeDensity
x.AshDensity = bd.AshDensity
x.WhiteAshDensity = bd.WhiteAshDensity
//x.RedSporeDensity = bd.RedSporeDensity
//x.BlueSporeDensity = bd.BlueSporeDensity
//x.AshDensity = bd.AshDensity
//x.WhiteAshDensity = bd.WhiteAshDensity
x.FoliageSnow = bd.FoliageSnow
x.Depth = bd.Depth
x.Scale = bd.Scale
x.MapWaterColour = bd.MapWaterColour
@@ -86,19 +94,20 @@ func (x *BiomeDefinition) FromLatest(bd protocol.BiomeDefinition) BiomeDefinitio
func (x *BiomeDefinition) ToLatest() protocol.BiomeDefinition {
return protocol.BiomeDefinition{
NameIndex: x.NameIndex,
BiomeID: x.BiomeID,
Temperature: x.Temperature,
Downfall: x.Downfall,
RedSporeDensity: x.RedSporeDensity,
BlueSporeDensity: x.BlueSporeDensity,
AshDensity: x.AshDensity,
WhiteAshDensity: x.WhiteAshDensity,
Depth: x.Depth,
Scale: x.Scale,
MapWaterColour: x.MapWaterColour,
Rain: x.Rain,
Tags: x.Tags,
ChunkGeneration: x.ChunkGeneration,
NameIndex: x.NameIndex,
BiomeID: x.BiomeID,
Temperature: x.Temperature,
Downfall: x.Downfall,
//RedSporeDensity: x.RedSporeDensity,
//BlueSporeDensity: x.BlueSporeDensity,
//AshDensity: x.AshDensity,
//WhiteAshDensity: x.WhiteAshDensity,
FoliageSnow: x.FoliageSnow,
Depth: x.Depth,
Scale: x.Scale,
MapWaterColour: x.MapWaterColour,
Rain: x.Rain,
Tags: x.Tags,
ChunkGeneration: x.ChunkGeneration,
}
}

View File

@@ -3,6 +3,7 @@ package proto
import "github.com/sandertv/gophertunnel/minecraft/protocol"
const (
ID844 = 844 // v1.21.110
ID827 = 827 // v1.21.100
ID819 = 819 // v1.21.93
ID818 = 818 // v1.21.90

View File

@@ -127,6 +127,8 @@ func convertPacketFunc(pid uint32, cur func() packet.Packet) func() packet.Packe
return func() packet.Packet { return &legacypacket.PlayerList{} }
case packet.IDSubChunk:
return func() packet.Packet { return &legacypacket.SubChunk{} }
case packet.IDGameRulesChanged:
return func() packet.Packet { return &legacypacket.GameRulesChanged{} }
default:
return cur
}
@@ -436,12 +438,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
}
case *packet.PlayerArmourDamage:
pks[pkIndex] = &legacypacket.PlayerArmourDamage{
Bitset: pk.Bitset,
HelmetDamage: pk.HelmetDamage,
ChestplateDamage: pk.ChestplateDamage,
LeggingsDamage: pk.LeggingsDamage,
BootsDamage: pk.BootsDamage,
BodyDamage: pk.BodyDamage,
List: pk.List,
}
case *packet.SetTitle:
pks[pkIndex] = &legacypacket.SetTitle{
@@ -753,6 +750,10 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
Position: pk.Position,
SubChunkEntries: entries,
}
case *packet.GameRulesChanged:
pks[pkIndex] = &legacypacket.GameRulesChanged{
GameRules: pk.GameRules,
}
}
}
@@ -1017,12 +1018,7 @@ func (p *Protocol) upgradePackets(pks []packet.Packet, conn *minecraft.Conn) []p
}
case *legacypacket.PlayerArmourDamage:
pks[pkIndex] = &packet.PlayerArmourDamage{
Bitset: pk.Bitset,
HelmetDamage: pk.HelmetDamage,
ChestplateDamage: pk.ChestplateDamage,
LeggingsDamage: pk.LeggingsDamage,
BootsDamage: pk.BootsDamage,
BodyDamage: pk.BodyDamage,
List: pk.List,
}
case *legacypacket.SetTitle:
pks[pkIndex] = &packet.SetTitle{
@@ -1296,6 +1292,10 @@ func (p *Protocol) upgradePackets(pks []packet.Packet, conn *minecraft.Conn) []p
Position: pk.Position,
SubChunkEntries: entries,
}
case *legacypacket.GameRulesChanged:
pks[pkIndex] = &packet.GameRulesChanged{
GameRules: pk.GameRules,
}
}
}
return pks

View File

@@ -9,7 +9,7 @@ import (
const (
// ItemVersion766 ...
ItemVersion766 = 221
ItemVersion766 = 231
// BlockVersion766 ...
BlockVersion766 int32 = (1 << 24) | (21 << 16) | (50 << 8)
)

View File

@@ -9,7 +9,7 @@ import (
const (
// ItemVersion776 ...
ItemVersion776 = 241
ItemVersion776 = 231
// BlockVersion776 ...
BlockVersion776 int32 = (1 << 24) | (21 << 16) | (60 << 8)
)

View File

@@ -9,7 +9,7 @@ import (
const (
// ItemVersion786 ...
ItemVersion786 = 241
ItemVersion786 = 231
// BlockVersion786 ...
BlockVersion786 int32 = (1 << 24) | (21 << 16) | (70 << 8)
)

View File

@@ -9,7 +9,7 @@ import (
const (
// ItemVersion800 ...
ItemVersion800 = 251
ItemVersion800 = 231
// BlockVersion800 ...
BlockVersion800 int32 = (1 << 24) | (21 << 16) | (80 << 8)
)

View File

@@ -9,7 +9,7 @@ import (
const (
// ItemVersion818 ...
ItemVersion818 = 261
ItemVersion818 = 231
// BlockVersion818 ...
BlockVersion818 int32 = (1 << 24) | (21 << 16) | (90 << 8)
)

View File

@@ -9,7 +9,7 @@ import (
const (
// ItemVersion819 ...
ItemVersion819 = 261
ItemVersion819 = 231
// BlockVersion819 ...
BlockVersion819 int32 = (1 << 24) | (21 << 16) | (90 << 8)
)

View File

@@ -3,32 +3,31 @@ package legacyver
import (
_ "embed"
"github.com/akmalfairuz/legacy-version/legacyver/proto"
"github.com/akmalfairuz/legacy-version/mapping"
)
const (
// ItemVersion827 ...
ItemVersion827 = 271
ItemVersion827 = 241
// BlockVersion827 ...
BlockVersion827 int32 = (1 << 24) | (21 << 16) | (100 << 8)
)
var (
//go:embed data/dragonfly_items.json
dragonflyLatestItemList []byte
//go:embed data/required_item_list_827.json
requiredItemList827 []byte
//go:embed data/block_states_827.nbt
blockStateData827 []byte
itemMappingLatestPocketMine = mapping.NewItemMapping(requiredItemList827, ItemVersion827)
itemMappingLatestDragonfly = mapping.NewItemMapping(dragonflyLatestItemList, ItemVersion827)
blockMappingLatest = mapping.NewBlockMapping(blockStateData827)
)
func itemMappingLatest(dragonflyMapping bool) mapping.Item {
if dragonflyMapping {
return itemMappingLatestDragonfly
func New827(dragonflyMapping bool) *Protocol {
itemMapping := mapping.NewItemMapping(requiredItemList827, ItemVersion827)
blockTranslator := lookupOrCreateBlockTranslator(827, BlockVersion827, blockStateData827)
return &Protocol{
ver: "1.21.100",
id: proto.ID827,
blockTranslator: blockTranslator,
itemTranslator: NewItemTranslator(itemMapping, itemMappingLatest(dragonflyMapping), blockTranslator.BlockMapping(), blockMappingLatest),
}
return itemMappingLatestPocketMine
}

34
legacyver/v844.go Normal file
View File

@@ -0,0 +1,34 @@
package legacyver
import (
_ "embed"
"github.com/akmalfairuz/legacy-version/mapping"
)
const (
// ItemVersion844 ...
ItemVersion844 = 241
// BlockVersion844 ...
BlockVersion844 int32 = (1 << 24) | (21 << 16) | (110 << 8)
)
var (
//go:embed data/dragonfly_items.json
dragonflyLatestItemList []byte
//go:embed data/required_item_list_844.json
requiredItemList844 []byte
//go:embed data/block_states_844.nbt
blockStateData844 []byte
itemMappingLatestPocketMine = mapping.NewItemMapping(requiredItemList844, ItemVersion844)
itemMappingLatestDragonfly = mapping.NewItemMapping(dragonflyLatestItemList, ItemVersion844)
blockMappingLatest = mapping.NewBlockMapping(blockStateData844)
)
func itemMappingLatest(dragonflyMapping bool) mapping.Item {
if dragonflyMapping {
return itemMappingLatestDragonfly
}
return itemMappingLatestPocketMine
}