This commit is contained in:
2024-09-18 19:58:25 +02:00
commit efd6d64d01
9 changed files with 2782 additions and 0 deletions

361
playPackets.go Normal file
View File

@@ -0,0 +1,361 @@
package main
import (
"bufio"
"bytes"
"github.com/Tnze/go-mc/nbt"
)
func (player *Player) sendBundleDelimiter() error {
return player.sendPacket(0x00, &bytes.Buffer{})
}
func (player *Player) sendSpawnEntity(entity *Entity) error {
var buf bytes.Buffer
entity.add(&buf)
return player.sendPacket(0x01, &buf)
}
func (player *Player) sendSpawnXP(xpOrb XPOrb) error {
var buf bytes.Buffer
xpOrb.add(&buf)
return player.sendPacket(0x02, &buf)
}
func (player *Player) sendEntityAnimation(entity *Entity) error {
var buf bytes.Buffer
addVarint(&buf, entity.ID)
addByte(&buf, entity.Animation)
return player.sendPacket(0x03, &buf)
}
func (player *Player) sendAwardStatistics() error {
var buf bytes.Buffer
addVarint(&buf, int32(len(player.statistics)))
for _, stat := range player.statistics {
addVarint(&buf, stat.CategoryID)
addVarint(&buf, stat.StatisticID)
addVarint(&buf, stat.Value)
}
return player.sendPacket(0x04, &buf)
}
func (player *Player) sendBlockChangeACK(seqID int32) error {
var buf bytes.Buffer
addVarint(&buf, seqID)
return player.sendPacket(0x05, &buf)
}
func (player *Player) sendBlockDestroyStage(entity *Entity, block *Block) error {
var buf bytes.Buffer
addVarint(&buf, entity.ID)
block.Position.add(&buf)
addByte(&buf, block.DestroyStage)
return player.sendPacket(0x06, &buf)
}
func (player *Player) sendBlockEntityData(entity *Entity, block *Block) error {
var buf bytes.Buffer
block.Position.add(&buf)
addVarint(&buf, entity.ID)
var nbtBuf bytes.Buffer
nbtWriter := bufio.NewWriter(&nbtBuf)
nbtEnc := nbt.NewEncoder(nbtWriter)
for key, val := range block.BlockEntityData {
err := nbtEnc.Encode(val, key)
if err != nil {
return err
}
}
nbtWriter.Flush()
buf.ReadFrom(&nbtBuf)
return player.sendPacket(0x07, &buf)
}
func (player *Player) sendBlockAction(block *Block, actionID uint8, actionParam uint8) error {
var buf bytes.Buffer
block.Position.add(&buf)
addByte(&buf, actionID)
addByte(&buf, actionParam)
addVarint(&buf, block.BlockTypeID)
return player.sendPacket(0x08, &buf)
}
func (player *Player) sendBlockUpdate(block *Block) error {
var buf bytes.Buffer
block.Position.add(&buf)
addVarint(&buf, block.BlockStateID)
return player.sendPacket(0x09, &buf)
}
func (player *Player) sendDifficulty() error {
var buf bytes.Buffer
addByte(&buf, world.Difficulty)
addBool(&buf, world.DifficultyLocked)
return player.sendPacket(0x0B, &buf)
}
func (player *Player) sendChunks() error {
//var buf bytes.Buffer
var bufFinished bytes.Buffer
err := player.sendPacket(0x0D, &bytes.Buffer{}) //chunk batch start
if err != nil {
return err
}
//count:= int32(len(chunks))
count := int32(0)
addVarint(&bufFinished, count)
err = player.sendPacket(0x0C, &bufFinished) //chunk batch end
if err != nil {
return err
}
return nil
}
//0x0E is chunk biomes, might implement later
//0x10 is Command Suggestions Response, might implement later
//0x11 is Commands, might implement later
func (player *Player) sendCloseContainer(windowID uint8) error {
var buf bytes.Buffer
addByte(&buf, windowID)
return player.sendPacket(0x12, &buf)
}
func (player *Player) sendContainerContent(windowID uint8, slots []*Slot, cursor *Slot) error {
var buf bytes.Buffer
addByte(&buf, windowID)
addVarint(&buf, player.lastContainerStateID)
player.lastContainerStateID++
addVarint(&buf, int32(len(slots)))
for _, slot := range slots {
slot.add(&buf)
}
cursor.add(&buf)
return player.sendPacket(0x13, &buf)
}
func (player *Player) sendContainerProperty(windowID uint8, property int16, value int16) error {
var buf bytes.Buffer
addByte(&buf, windowID)
addInt16(&buf, property)
addInt16(&buf, value)
return player.sendPacket(0x14, &buf)
}
func (player *Player) sendContainerSlot(windowID uint8, slotIndex int16, slot *Slot) error {
var buf bytes.Buffer
addByte(&buf, windowID)
addVarint(&buf, player.lastContainerStateID)
player.lastContainerStateID++
addInt16(&buf, slotIndex)
slot.add(&buf)
return player.sendPacket(0x15, &buf)
}
//0x16 is cookie, might get implemented cross-state
func (player *Player) sendCooldown(itemID int32, cooldownTicks int32) error {
var buf bytes.Buffer
addVarint(&buf, itemID)
addVarint(&buf, cooldownTicks)
return player.sendPacket(0x17, &buf)
}
func (player *Player) sendChatSuggestions(action int32, entries []string) error {
var buf bytes.Buffer
addVarint(&buf, action)
addVarint(&buf, int32(len(entries)))
for _, entry := range entries {
addString(&buf, entry)
}
return player.sendPacket(0x18, &buf)
}
//0x19 is plugin message, should be implemented globally
func (player *Player) sendDamageEvent(damagedEntity *Entity, damageType int32, sourceEntity *Entity, sourceDirectEntity *Entity) error {
var buf bytes.Buffer
addVarint(&buf, damagedEntity.ID)
addVarint(&buf, damageType)
addVarint(&buf, sourceEntity.ID)
if sourceDirectEntity != nil {
addVarint(&buf, sourceDirectEntity.ID)
} else {
addVarint(&buf, sourceEntity.ID)
}
addBool(&buf, true)
sourceEntity.Position.add(&buf)
return player.sendPacket(0x1A, &buf)
}
func (player *Player) sendDebugSample(sampleType int32, sample []int64) error {
var buf bytes.Buffer
addVarint(&buf, int32(len(sample)))
for _, val := range sample {
addInt64(&buf, val)
}
addVarint(&buf, sampleType)
return player.sendPacket(0x1B, &buf)
}
func (player *Player) deleteMessage(messageID int32, signature []byte) error {
var buf bytes.Buffer
addVarint(&buf, messageID)
if messageID == 0 {
for _, sigPiece := range signature {
addByte(&buf, sigPiece)
}
}
return player.sendPacket(0x1C, &buf)
}
//0x1D is disconnect, should be implemented globally
func (player *Player) sendDisguisedChatMessage(message TextComponent, typeID int32, senderName TextComponent, targetName *TextComponent) error {
var buf bytes.Buffer
addTextComponent(&buf, message)
addVarint(&buf, typeID)
addTextComponent(&buf, senderName)
hasTargetName := targetName != nil
addBool(&buf, hasTargetName)
if hasTargetName {
addTextComponent(&buf, *targetName)
}
return player.sendPacket(0x1E, &buf)
}
func (player *Player) sendEntityEvent(entity *Entity) error {
var buf bytes.Buffer
addInt32(&buf, entity.ID)
addByte(&buf, byte(entity.status))
return player.sendPacket(0x1F, &buf)
}
func (player *Player) sendExplosion(explosion *Explosion) error {
var buf bytes.Buffer
explosion.Position.add(&buf)
addFloat32(&buf, explosion.Strength)
addVarint(&buf, int32(len(explosion.AffectedBlockRecords)))
for _, affectedBlockRecord := range explosion.AffectedBlockRecords {
affectedBlockRecord.add(&buf)
}
explosion.PlayerMotion.add(&buf)
addVarint(&buf, explosion.BlockInteraction)
explosion.SmallExplosionParticle.addExplosion(&buf)
explosion.LargeExplosionParticle.addExplosion(&buf)
explosion.ExplosionSound.add(&buf)
return player.sendPacket(0x20, &buf)
}
func (player *Player) sendUnloadChunk(chunk *Chunk) error {
var buf bytes.Buffer
addInt32(&buf, chunk.Z)
addInt32(&buf, chunk.X)
return player.sendPacket(0x21, &buf)
}
func (player *Player) sendGameEvent(event uint8, value float32) error {
var buf bytes.Buffer
addByte(&buf, event)
addFloat32(&buf, value)
return player.sendPacket(0x22, &buf)
}
func (player *Player) sendHorseScreen(windowID uint8, slotCount int32, entityID int32) error {
var buf bytes.Buffer
addByte(&buf, windowID)
addVarint(&buf, slotCount)
addInt32(&buf, entityID)
return player.sendPacket(0x23, &buf)
}
// Example usage in sendHurtAnimation
func (player *Player) sendHurtAnimation(attacker *Entity) error {
var buf bytes.Buffer
addVarint(&buf, attacker.ID)
// Calculate yaw based on attacker and player positions
attackYaw := calculateYaw(attacker.Position, player.Position)
addFloat32(&buf, attackYaw)
return player.sendPacket(0x24, &buf)
}
func (player *Player) sendWorldBorder(border *WorldBorder) error {
var buf bytes.Buffer
addFloat64(&buf, border.X)
addFloat64(&buf, border.Z)
addFloat64(&buf, border.OldDiameter)
addFloat64(&buf, border.NewDiameter)
addVarlong(&buf, border.Speed)
addVarint(&buf, border.PortalTeleportBoundary)
addVarint(&buf, border.WarningBlocks)
addVarint(&buf, border.WarningTime)
return player.sendPacket(0x25, &buf)
}
//0x26 is keepalive
//0x27 is chunk and light //TODO LATER
func (player *Player) sendWorldEvent(event int32, position BlockPosition, data int32, disableRelativeVolume bool) error {
var buf bytes.Buffer
addInt32(&buf, event)
position.add(&buf)
addInt32(&buf, data)
addBool(&buf, disableRelativeVolume)
return player.sendPacket(0x28, &buf)
}
func (player *Player) sendParticle(particle *Particle, count int32) error {
var buf bytes.Buffer
particle.addPacket(&buf, count)
return player.sendPacket(0x29, &buf)
}
//0x2A is Update light levels //TODO LATER
func (player *Player) sendPlayStart() error {
var buf bytes.Buffer
addInt32(&buf, player.Entity.ID)
addBool(&buf, world.Hardcore)
addVarint(&buf, int32(len(world.Dimensions)))
for _, dimension := range world.Dimensions {
addString(&buf, dimension.Name)
}
addVarint(&buf, maxPlayers)
addVarint(&buf, world.ViewDistance)
addVarint(&buf, world.SimulationDistance)
addBool(&buf, world.ReducedDebugInfo)
addBool(&buf, world.EnableRespawnScreen)
addBool(&buf, world.DoLimitedCrafting)
addVarint(&buf, player.Dimension.ID)
addString(&buf, player.Dimension.Name)
noise, err := world.Seed.MarshalBinary()
if err != nil {
return err
}
for i := 0; i < 8; i++ {
addByte(&buf, noise[i])
}
addByte(&buf, player.GameMode)
addByte(&buf, byte(player.PreviousGameMode))
addBool(&buf, world.Debug)
addBool(&buf, world.Flat)
hasDeathLocation := player.DeathDimension != nil
addBool(&buf, hasDeathLocation)
if hasDeathLocation {
addString(&buf, player.DeathDimension.Name)
player.DeathPosition.add(&buf)
}
addVarint(&buf, player.Entity.PortalCooldown)
addBool(&buf, world.EnforceSecureChat)
return player.sendPacket(0x2B, &buf)
}
//func (player *Player) sendMapItemData(mapId int32) error {
// mapEntry := world.m
//}