init
This commit is contained in:
716
structs.go
Normal file
716
structs.go
Normal file
@@ -0,0 +1,716 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
"github.com/google/uuid"
|
||||
"math"
|
||||
"net"
|
||||
)
|
||||
|
||||
type Version struct {
|
||||
Name string `json:"name"`
|
||||
Protocol int `json:"protocol"`
|
||||
}
|
||||
|
||||
type PlayerSample struct {
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type Players struct {
|
||||
Max int32 `json:"max"`
|
||||
Online int `json:"online"`
|
||||
Sample []PlayerSample `json:"sample"`
|
||||
}
|
||||
|
||||
type Description struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type ServerStatus struct {
|
||||
Version Version `json:"version"`
|
||||
Players Players `json:"players,omitempty"`
|
||||
Description Description `json:"description,omitempty"`
|
||||
Favicon string `json:"favicon,omitempty"`
|
||||
EnforcesSecureChat bool `json:"enforcesSecureChat"`
|
||||
}
|
||||
|
||||
type Player struct {
|
||||
conn net.Conn
|
||||
|
||||
state int32
|
||||
version int32
|
||||
requestedAddress string
|
||||
requestedPort uint16
|
||||
compressionThreshold int32
|
||||
verifyToken []byte
|
||||
decryptStream cipher.Stream
|
||||
encryptStream cipher.Stream
|
||||
reader *bufio.Reader
|
||||
profile MojangProfile
|
||||
transferred bool
|
||||
resourcePackResponse map[uuid.UUID]int32
|
||||
knownPacks []DatapackInfo
|
||||
Entity *Entity
|
||||
Dimension *Dimension
|
||||
DeathDimension *Dimension
|
||||
DeathPosition BlockPosition
|
||||
|
||||
Position EntityPosition
|
||||
|
||||
GameMode uint8
|
||||
PreviousGameMode int8
|
||||
|
||||
locale string
|
||||
viewDistance int8
|
||||
chatMode int32
|
||||
chatColors bool
|
||||
skinParts uint8
|
||||
isRightHanded bool
|
||||
textFiltering bool
|
||||
serverListing bool
|
||||
|
||||
keepAlivePayload int64
|
||||
keepAliveSentTimestamp int64
|
||||
keepAliveReceivedTimestamp int64
|
||||
|
||||
pingID uint32
|
||||
pingSentTimestamp int64
|
||||
pingReceivedTimestamp int64
|
||||
statistics []StatisticPiece
|
||||
|
||||
lastContainerStateID int32
|
||||
|
||||
name string
|
||||
uuid uuid.UUID
|
||||
}
|
||||
|
||||
type Dimension struct {
|
||||
ID int32
|
||||
Name string
|
||||
}
|
||||
|
||||
type World struct {
|
||||
Difficulty uint8
|
||||
DifficultyLocked bool
|
||||
|
||||
Hardcore bool
|
||||
Dimensions []Dimension
|
||||
ViewDistance int32
|
||||
SimulationDistance int32
|
||||
ReducedDebugInfo bool
|
||||
EnableRespawnScreen bool
|
||||
DoLimitedCrafting bool
|
||||
Seed uuid.UUID
|
||||
Debug bool
|
||||
Flat bool
|
||||
EnforceSecureChat bool
|
||||
|
||||
Entities []Entity
|
||||
Players []Player
|
||||
RegistryDataThings []RegistryData
|
||||
FeatureFlags []string
|
||||
UpdateTags []UpdateTag
|
||||
DataPacks []DatapackInfo
|
||||
ReportDetails map[string]string
|
||||
ServerLinks []ServerLink
|
||||
|
||||
Maps map[int32]Map
|
||||
}
|
||||
|
||||
type StatisticPiece struct {
|
||||
CategoryID int32
|
||||
StatisticID int32
|
||||
Value int32
|
||||
}
|
||||
|
||||
type EntityPosition struct {
|
||||
X float64
|
||||
Y float64
|
||||
Z float64
|
||||
}
|
||||
|
||||
type FloatOffset struct {
|
||||
X float32
|
||||
Y float32
|
||||
Z float32
|
||||
}
|
||||
|
||||
type BlockPosition struct {
|
||||
X int32
|
||||
Y int16
|
||||
Z int32
|
||||
}
|
||||
|
||||
type AffectedBlockRecord struct {
|
||||
OffsetX int8
|
||||
OffsetY int8
|
||||
OffsetZ int8
|
||||
}
|
||||
|
||||
func (affectedBlockRecord *AffectedBlockRecord) add(buf *bytes.Buffer) {
|
||||
addByte(buf, byte(affectedBlockRecord.OffsetX))
|
||||
addByte(buf, byte(affectedBlockRecord.OffsetY))
|
||||
addByte(buf, byte(affectedBlockRecord.OffsetZ))
|
||||
}
|
||||
|
||||
type ExplosionSound struct {
|
||||
Name string
|
||||
FixedRange float32
|
||||
}
|
||||
|
||||
func (explosionSound *ExplosionSound) add(buf *bytes.Buffer) {
|
||||
addString(buf, explosionSound.Name)
|
||||
hasFixedRange := explosionSound.FixedRange > 0
|
||||
addBool(buf, hasFixedRange)
|
||||
if hasFixedRange {
|
||||
addFloat32(buf, explosionSound.FixedRange)
|
||||
}
|
||||
}
|
||||
|
||||
type Particle struct {
|
||||
ParticleID int32
|
||||
BlockState int32 // Used by block-related particles
|
||||
FromColor [3]float32 // Used for color particles (RGB)
|
||||
ToColor [3]float32 // Used for dust_color_transition particles (RGB)
|
||||
Scale float32 // Used for dust/dust_color_transition particles
|
||||
PositionSourceType int32 // Used for vibration particles
|
||||
BlockPosition BlockPosition // Used for vibration particles (minecraft:block)
|
||||
EntityID int32 // Used for vibration particles (minecraft:entity)
|
||||
EntityEyeHeight float32 // Used for vibration particles (minecraft:entity)
|
||||
Ticks int32 // Used for vibration particles
|
||||
Delay int32 // Used for shriek particles
|
||||
|
||||
Count int32
|
||||
LongDistance bool
|
||||
Position EntityPosition
|
||||
Offset FloatOffset
|
||||
MaxSpeed float32
|
||||
}
|
||||
|
||||
type WorldBorder struct {
|
||||
X float64
|
||||
Z float64
|
||||
OldDiameter float64
|
||||
NewDiameter float64
|
||||
Speed int64
|
||||
PortalTeleportBoundary int32
|
||||
WarningBlocks int32
|
||||
WarningTime int32
|
||||
}
|
||||
|
||||
// Compute yaw between two positions
|
||||
func calculateYaw(attackerPos, playerPos EntityPosition) float32 {
|
||||
deltaX := attackerPos.X - playerPos.X
|
||||
deltaZ := attackerPos.Z - playerPos.Z
|
||||
|
||||
// atan2 returns the angle in radians, we convert it to degrees
|
||||
yaw := math.Atan2(deltaZ, deltaX) * (180 / math.Pi)
|
||||
|
||||
// In Minecraft, yaw 0 points towards positive Z, so we adjust the yaw to this system
|
||||
yaw = -yaw + 90
|
||||
|
||||
// Normalize yaw to be between 0 and 360 degrees
|
||||
if yaw < 0 {
|
||||
yaw += 360
|
||||
}
|
||||
|
||||
return float32(yaw)
|
||||
}
|
||||
|
||||
func encodeARGB(color [3]float32) int32 {
|
||||
// Encodes RGB color values into an ARGB int (alpha assumed to be 255)
|
||||
r := int32(color[0] * 255)
|
||||
g := int32(color[1] * 255)
|
||||
b := int32(color[2] * 255)
|
||||
a := int32(255)
|
||||
return (a << 24) | (r << 16) | (g << 8) | b
|
||||
}
|
||||
|
||||
func clampScale(scale float32) float32 {
|
||||
// Clamps the scale between 0.01 and 4.0
|
||||
if scale < 0.01 {
|
||||
return 0.01
|
||||
}
|
||||
if scale > 4.0 {
|
||||
return 4.0
|
||||
}
|
||||
return scale
|
||||
}
|
||||
|
||||
func (p *Particle) addPacket(buf *bytes.Buffer, count int32) {
|
||||
addBool(buf, p.LongDistance)
|
||||
p.Position.add(buf)
|
||||
p.Offset.add(buf)
|
||||
addFloat32(buf, p.MaxSpeed)
|
||||
addInt32(buf, count)
|
||||
addInt32(buf, p.ParticleID)
|
||||
|
||||
// Handle based on particle ID
|
||||
switch p.ParticleID {
|
||||
case 1, 2, 28, 105: // minecraft:block, minecraft:block_marker, falling_dust, dust_pillar
|
||||
addVarint(buf, p.BlockState)
|
||||
|
||||
case 13: // minecraft:dust
|
||||
addFloat32(buf, p.FromColor[0])
|
||||
addFloat32(buf, p.FromColor[1])
|
||||
addFloat32(buf, p.FromColor[2])
|
||||
addFloat32(buf, clampScale(p.Scale))
|
||||
|
||||
case 14: // minecraft:dust_color_transition
|
||||
addFloat32(buf, p.FromColor[0])
|
||||
addFloat32(buf, p.FromColor[1])
|
||||
addFloat32(buf, p.FromColor[2])
|
||||
addFloat32(buf, p.ToColor[0])
|
||||
addFloat32(buf, p.ToColor[1])
|
||||
addFloat32(buf, p.ToColor[2])
|
||||
addFloat32(buf, clampScale(p.Scale))
|
||||
|
||||
case 20: // minecraft:entity_effect
|
||||
addInt32(buf, encodeARGB(p.FromColor))
|
||||
|
||||
case 45: // minecraft:vibration
|
||||
addVarint(buf, p.PositionSourceType)
|
||||
if p.PositionSourceType == 0 {
|
||||
p.BlockPosition.add(buf)
|
||||
} else if p.PositionSourceType == 1 {
|
||||
addVarint(buf, p.EntityID)
|
||||
addFloat32(buf, p.EntityEyeHeight)
|
||||
}
|
||||
addVarint(buf, p.Ticks)
|
||||
|
||||
case 99: // minecraft:shriek
|
||||
addVarint(buf, p.Delay)
|
||||
|
||||
// Particles with no additional data
|
||||
case 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 100, 101, 102, 103, 104, 106, 107, 108:
|
||||
// No additional data required
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Particle) addExplosion(buf *bytes.Buffer) {
|
||||
addInt32(buf, p.ParticleID)
|
||||
|
||||
// Handle based on particle ID
|
||||
switch p.ParticleID {
|
||||
case 1, 2, 28, 105: // minecraft:block, minecraft:block_marker, falling_dust, dust_pillar
|
||||
addVarint(buf, p.BlockState)
|
||||
|
||||
case 13: // minecraft:dust
|
||||
addFloat32(buf, p.FromColor[0])
|
||||
addFloat32(buf, p.FromColor[1])
|
||||
addFloat32(buf, p.FromColor[2])
|
||||
addFloat32(buf, clampScale(p.Scale))
|
||||
|
||||
case 14: // minecraft:dust_color_transition
|
||||
addFloat32(buf, p.FromColor[0])
|
||||
addFloat32(buf, p.FromColor[1])
|
||||
addFloat32(buf, p.FromColor[2])
|
||||
addFloat32(buf, p.ToColor[0])
|
||||
addFloat32(buf, p.ToColor[1])
|
||||
addFloat32(buf, p.ToColor[2])
|
||||
addFloat32(buf, clampScale(p.Scale))
|
||||
|
||||
case 20: // minecraft:entity_effect
|
||||
addInt32(buf, encodeARGB(p.FromColor))
|
||||
|
||||
case 45: // minecraft:vibration
|
||||
addVarint(buf, p.PositionSourceType)
|
||||
if p.PositionSourceType == 0 {
|
||||
p.BlockPosition.add(buf)
|
||||
} else if p.PositionSourceType == 1 {
|
||||
addVarint(buf, p.EntityID)
|
||||
addFloat32(buf, p.EntityEyeHeight)
|
||||
}
|
||||
addVarint(buf, p.Ticks)
|
||||
|
||||
case 99: // minecraft:shriek
|
||||
addVarint(buf, p.Delay)
|
||||
|
||||
// Particles with no additional data
|
||||
case 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 100, 101, 102, 103, 104, 106, 107, 108:
|
||||
// No additional data required
|
||||
}
|
||||
}
|
||||
|
||||
type Explosion struct {
|
||||
Position EntityPosition
|
||||
Strength float32
|
||||
AffectedBlockRecords []AffectedBlockRecord
|
||||
PlayerMotion EntityPosition
|
||||
BlockInteraction int32
|
||||
SmallExplosionParticle Particle
|
||||
LargeExplosionParticle Particle
|
||||
ExplosionSound ExplosionSound
|
||||
}
|
||||
|
||||
type Slot struct {
|
||||
Count int32
|
||||
ItemID int32
|
||||
ComponentsToAdd map[int32]any
|
||||
ComponentsToRemove []int32
|
||||
}
|
||||
|
||||
func (slot *Slot) add(buf *bytes.Buffer) {
|
||||
addVarint(buf, slot.Count)
|
||||
if slot.Count > 0 {
|
||||
addVarint(buf, slot.ItemID)
|
||||
addVarint(buf, int32(len(slot.ComponentsToAdd)))
|
||||
addVarint(buf, int32(len(slot.ComponentsToRemove)))
|
||||
for componentID, component := range slot.ComponentsToAdd {
|
||||
addVarint(buf, componentID)
|
||||
component = component //TODO IMPLEMENT ALL THESE STUPID COMPONENTS
|
||||
}
|
||||
for _, componentID := range slot.ComponentsToRemove {
|
||||
addVarint(buf, componentID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PalettedContainer represents a palette-based storage of entries.
|
||||
type PalettedContainer struct {
|
||||
BitsPerEntry uint8
|
||||
Palette []int32
|
||||
DataArray []uint64 // Packed data for blocks or biomes
|
||||
}
|
||||
|
||||
// AddEntry adds an entry (block or biome) to the palette and updates the DataArray.
|
||||
func (p *PalettedContainer) AddEntry(entry int32, index int) {
|
||||
// Check if the entry already exists in the palette.
|
||||
for i, val := range p.Palette {
|
||||
if val == entry {
|
||||
// Entry already exists, no need to addExplosion to palette.
|
||||
p.setEntryAtIndex(i, index)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new entry to the palette.
|
||||
p.Palette = append(p.Palette, entry)
|
||||
|
||||
// Use the index of the new entry in the palette and store it in the DataArray.
|
||||
p.setEntryAtIndex(len(p.Palette)-1, index)
|
||||
}
|
||||
|
||||
// setEntryAtIndex sets the palette index for the block/biome at the specified index in the DataArray.
|
||||
func (p *PalettedContainer) setEntryAtIndex(paletteIndex int, index int) {
|
||||
// Each entry is packed into the DataArray with the specified BitsPerEntry.
|
||||
entriesPerLong := 64 / p.BitsPerEntry
|
||||
longIndex := index / int(entriesPerLong)
|
||||
bitIndex := (index % int(entriesPerLong)) * int(p.BitsPerEntry)
|
||||
|
||||
// Clear the bits at the specified location before setting the new value.
|
||||
mask := uint64(math.MaxUint64>>(64-p.BitsPerEntry)) << bitIndex
|
||||
p.DataArray[longIndex] &= ^mask
|
||||
|
||||
// Set the new value.
|
||||
p.DataArray[longIndex] |= (uint64(paletteIndex) & (math.MaxUint64 >> (64 - p.BitsPerEntry))) << bitIndex
|
||||
}
|
||||
|
||||
// add serializes the PalettedContainer to a buffer for network transmission.
|
||||
func (p *PalettedContainer) add(buf *bytes.Buffer) error {
|
||||
// Write BitsPerEntry
|
||||
buf.WriteByte(p.BitsPerEntry)
|
||||
|
||||
// Write Palette
|
||||
if len(p.Palette) > 0 {
|
||||
// Write the length of the palette as a VarInt.
|
||||
addVarint(buf, int32(len(p.Palette)))
|
||||
// Write each palette entry as a VarInt.
|
||||
for _, entry := range p.Palette {
|
||||
addVarint(buf, entry)
|
||||
}
|
||||
} else {
|
||||
// Write a palette length of 0 for a global palette.
|
||||
addVarint(buf, 0)
|
||||
}
|
||||
|
||||
// Write DataArray
|
||||
// First, write the length of the DataArray (in terms of the number of longs).
|
||||
addVarint(buf, int32(len(p.DataArray)))
|
||||
// Write each uint64 in the DataArray as a little-endian long.
|
||||
for _, data := range p.DataArray {
|
||||
err := binary.Write(buf, binary.BigEndian, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChunkSection represents a 16x16x16 section of a chunk.
|
||||
type ChunkSection struct {
|
||||
BlockCount uint16 // Non-air block count
|
||||
BlockStates PalettedContainer // Block palette and states
|
||||
Biomes PalettedContainer // Biome palette and data
|
||||
}
|
||||
|
||||
// add serializes the ChunkSection into the buffer.
|
||||
func (cs *ChunkSection) add(buf *bytes.Buffer) error {
|
||||
err := binary.Write(buf, binary.BigEndian, cs.BlockCount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write BlockStates and Biomes.
|
||||
err = cs.BlockStates.add(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cs.Biomes.add(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Chunk represents a chunk column, containing multiple chunk sections.
|
||||
type Chunk struct {
|
||||
X int32 // Chunk X coordinate
|
||||
Z int32 // Chunk Z coordinate
|
||||
Sections []ChunkSection // Chunk sections (16x16x16)
|
||||
}
|
||||
|
||||
// add serializes the Chunk into the buffer.
|
||||
func (c *Chunk) add(buf *bytes.Buffer) error {
|
||||
err := binary.Write(buf, binary.BigEndian, c.X)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = binary.Write(buf, binary.BigEndian, c.Z)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the number of sections as a VarInt.
|
||||
addVarint(buf, int32(len(c.Sections)))
|
||||
|
||||
// Write each chunk section.
|
||||
for _, section := range c.Sections {
|
||||
err := section.add(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Block struct {
|
||||
Position BlockPosition
|
||||
BlockEntityType int32
|
||||
BlockTypeID int32
|
||||
BlockStateID int32
|
||||
BlockEntityData map[string]any
|
||||
DestroyStage uint8
|
||||
}
|
||||
|
||||
type BossBar struct {
|
||||
UUID uuid.UUID
|
||||
Title TextComponent
|
||||
Health float32
|
||||
Color int32
|
||||
Division int32
|
||||
Flags uint8
|
||||
}
|
||||
|
||||
func (bossBar BossBar) add(player *Player) error {
|
||||
var buf bytes.Buffer
|
||||
addUUID(&buf, bossBar.UUID)
|
||||
addVarint(&buf, 0)
|
||||
addTextComponent(&buf, bossBar.Title)
|
||||
addFloat32(&buf, bossBar.Health)
|
||||
addVarint(&buf, bossBar.Color)
|
||||
addVarint(&buf, bossBar.Division)
|
||||
addByte(&buf, bossBar.Flags)
|
||||
return player.sendPacket(0x0A, &buf)
|
||||
}
|
||||
|
||||
func (bossBar BossBar) remove(player *Player) error {
|
||||
var buf bytes.Buffer
|
||||
addUUID(&buf, bossBar.UUID)
|
||||
addVarint(&buf, 1)
|
||||
return player.sendPacket(0x0A, &buf)
|
||||
}
|
||||
|
||||
func (bossBar BossBar) updateHealth(player *Player) error {
|
||||
var buf bytes.Buffer
|
||||
addUUID(&buf, bossBar.UUID)
|
||||
addVarint(&buf, 2)
|
||||
addFloat32(&buf, bossBar.Health)
|
||||
return player.sendPacket(0x0A, &buf)
|
||||
}
|
||||
|
||||
func (bossBar BossBar) updateTitle(player *Player) error {
|
||||
var buf bytes.Buffer
|
||||
addUUID(&buf, bossBar.UUID)
|
||||
addVarint(&buf, 3)
|
||||
addTextComponent(&buf, bossBar.Title)
|
||||
return player.sendPacket(0x0A, &buf)
|
||||
}
|
||||
|
||||
func (bossBar BossBar) updateStyle(player *Player) error {
|
||||
var buf bytes.Buffer
|
||||
addUUID(&buf, bossBar.UUID)
|
||||
addVarint(&buf, 4)
|
||||
addVarint(&buf, bossBar.Color)
|
||||
addVarint(&buf, bossBar.Division)
|
||||
return player.sendPacket(0x0A, &buf)
|
||||
}
|
||||
|
||||
func (bossBar BossBar) updateFlags(player *Player) error {
|
||||
var buf bytes.Buffer
|
||||
addUUID(&buf, bossBar.UUID)
|
||||
addVarint(&buf, 5)
|
||||
addByte(&buf, bossBar.Flags)
|
||||
return player.sendPacket(0x0A, &buf)
|
||||
}
|
||||
|
||||
func (blockPosition *BlockPosition) add(buf *bytes.Buffer) {
|
||||
var xBuf, yBuf, zBuf []byte
|
||||
binary.BigEndian.PutUint32(xBuf, uint32(blockPosition.X))
|
||||
binary.BigEndian.PutUint16(yBuf, uint16(blockPosition.Y))
|
||||
binary.BigEndian.PutUint32(zBuf, uint32(blockPosition.Z))
|
||||
|
||||
buf.Write(xBuf[0:26])
|
||||
buf.Write(zBuf[0:26])
|
||||
buf.Write(yBuf[0:12])
|
||||
}
|
||||
|
||||
func (entityPosition *EntityPosition) add(buf *bytes.Buffer) {
|
||||
addFloat64(buf, entityPosition.X)
|
||||
addFloat64(buf, entityPosition.Y)
|
||||
addFloat64(buf, entityPosition.Z)
|
||||
}
|
||||
|
||||
func (floatOffset *FloatOffset) add(buf *bytes.Buffer) {
|
||||
addFloat32(buf, floatOffset.X)
|
||||
addFloat32(buf, floatOffset.Y)
|
||||
addFloat32(buf, floatOffset.Z)
|
||||
}
|
||||
|
||||
type EntityRotation struct {
|
||||
Pitch uint8
|
||||
Yaw uint8
|
||||
HeadYaw uint8
|
||||
}
|
||||
|
||||
func (entityRotation *EntityRotation) add(buf *bytes.Buffer) {
|
||||
addByte(buf, entityRotation.Pitch)
|
||||
addByte(buf, entityRotation.Yaw)
|
||||
addByte(buf, entityRotation.HeadYaw)
|
||||
}
|
||||
|
||||
type Velocity struct {
|
||||
X float32
|
||||
Y float32
|
||||
Z float32
|
||||
}
|
||||
|
||||
func (velocity *Velocity) add(buf *bytes.Buffer) {
|
||||
addFloat32(buf, velocity.X)
|
||||
addFloat32(buf, velocity.Y)
|
||||
addFloat32(buf, velocity.Z)
|
||||
}
|
||||
|
||||
type Entity struct {
|
||||
ID int32
|
||||
UUID uuid.UUID
|
||||
Type int32
|
||||
Position EntityPosition
|
||||
Rotation EntityRotation
|
||||
Data int32
|
||||
Velocity Velocity
|
||||
Animation uint8
|
||||
status int8
|
||||
PortalCooldown int32
|
||||
}
|
||||
|
||||
func (entity *Entity) add(buf *bytes.Buffer) {
|
||||
addVarint(buf, entity.ID)
|
||||
addUUID(buf, entity.UUID)
|
||||
addVarint(buf, entity.Type)
|
||||
entity.Position.add(buf)
|
||||
entity.Rotation.add(buf)
|
||||
addVarint(buf, entity.Data)
|
||||
entity.Velocity.add(buf)
|
||||
}
|
||||
|
||||
type XPOrb struct {
|
||||
ID int32
|
||||
Position EntityPosition
|
||||
Count int16
|
||||
}
|
||||
|
||||
func (XPOrb *XPOrb) add(buf *bytes.Buffer) {
|
||||
addVarint(buf, XPOrb.ID)
|
||||
XPOrb.Position.add(buf)
|
||||
addInt16(buf, XPOrb.Count)
|
||||
}
|
||||
|
||||
type MapIcon struct {
|
||||
Type int32
|
||||
X int8
|
||||
Z int8
|
||||
Direction int8
|
||||
DisplayName *TextComponent
|
||||
}
|
||||
|
||||
func (MapIcon *MapIcon) add(buf *bytes.Buffer) {
|
||||
addVarint(buf, MapIcon.Type)
|
||||
addByte(buf, byte(MapIcon.X))
|
||||
addByte(buf, byte(MapIcon.Z))
|
||||
addByte(buf, byte(MapIcon.Direction))
|
||||
hasTextComponent := MapIcon.DisplayName != nil
|
||||
addBool(buf, hasTextComponent)
|
||||
if hasTextComponent {
|
||||
addTextComponent(buf, *MapIcon.DisplayName)
|
||||
}
|
||||
}
|
||||
|
||||
type Map struct {
|
||||
ID int32
|
||||
Scale int8
|
||||
Locked bool
|
||||
Icons []MapIcon
|
||||
|
||||
MapUpdateDataW uint8
|
||||
MapUpdateDataH uint8
|
||||
MapUpdateDataX uint8
|
||||
MapUpdateDataZ uint8
|
||||
MapUpdateData []uint8
|
||||
}
|
||||
|
||||
func (Map *Map) add(buf *bytes.Buffer) {
|
||||
addVarint(buf, Map.ID)
|
||||
addByte(buf, byte(Map.Scale))
|
||||
addBool(buf, Map.Locked)
|
||||
|
||||
iconCount := int32(len(Map.Icons))
|
||||
|
||||
addBool(buf, iconCount > 0)
|
||||
if iconCount > 0 {
|
||||
addVarint(buf, iconCount)
|
||||
for _, mapIcon := range Map.Icons {
|
||||
mapIcon.add(buf)
|
||||
}
|
||||
}
|
||||
|
||||
addByte(buf, Map.MapUpdateDataH)
|
||||
if Map.MapUpdateDataH > 0 {
|
||||
addByte(buf, Map.MapUpdateDataW)
|
||||
addByte(buf, Map.MapUpdateDataX)
|
||||
addByte(buf, Map.MapUpdateDataZ)
|
||||
addVarint(buf, int32(len(Map.MapUpdateData)))
|
||||
for _, mapUpdatePiece := range Map.MapUpdateData {
|
||||
addByte(buf, mapUpdatePiece)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user