init
This commit is contained in:
361
playPackets.go
Normal file
361
playPackets.go
Normal 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
|
||||
//}
|
Reference in New Issue
Block a user