diff --git a/core_commands/ban.go b/core_commands/ban.go index 8423f7f..42a454d 100644 --- a/core_commands/ban.go +++ b/core_commands/ban.go @@ -10,7 +10,7 @@ var ban_cmd = &commands.Command{ Name: "ban", RequiredPermissions: []string{"server.command.ban"}, Arguments: []commands.Argument{ - commands.NewEntityArgument("player", commands.EntityPlayerOnly), + commands.NewEntityArg("player", commands.EntityPlayerOnly), commands.NewStrArg("reason", commands.GreedyPhrase), }, Execute: func(ctx commands.CommandContext) { diff --git a/core_commands/deop.go b/core_commands/deop.go index d3bee55..389d683 100644 --- a/core_commands/deop.go +++ b/core_commands/deop.go @@ -8,7 +8,7 @@ var deop_cmd = &commands.Command{ Name: "deop", RequiredPermissions: []string{"server.command.deop"}, Arguments: []commands.Argument{ - commands.NewEntityArgument("player", commands.EntityPlayerOnly), + commands.NewEntityArg("player", commands.EntityPlayerOnly), }, Execute: func(ctx commands.CommandContext) { if len(ctx.Arguments) == 0 { diff --git a/core_commands/dimension.go b/core_commands/dimension.go index 77e39bf..02c5c3b 100644 --- a/core_commands/dimension.go +++ b/core_commands/dimension.go @@ -10,7 +10,7 @@ var dimension_cmd = &commands.Command{ Name: "dimension", RequiredPermissions: []string{"server.command.dimension"}, Arguments: []commands.Argument{ - commands.NewDimensionArgument("dimension"), + commands.NewDimensionArg("dimension"), }, Execute: func(ctx commands.CommandContext) { if len(ctx.Arguments) == 0 { diff --git a/core_commands/gamemode.go b/core_commands/gamemode.go index ef7f452..c5258eb 100644 --- a/core_commands/gamemode.go +++ b/core_commands/gamemode.go @@ -22,8 +22,8 @@ var gamemode_cmd = &commands.Command{ Name: "gamemode", RequiredPermissions: []string{"server.command.gamemode"}, Arguments: []commands.Argument{ - commands.NewGamemodeArgument("mode"), - commands.NewEntityArgument("player", commands.EntityPlayerOnly), + commands.NewGamemodeArg("mode"), + commands.NewEntityArg("player", commands.EntityPlayerOnly), }, Execute: func(ctx commands.CommandContext) { if len(ctx.Arguments) == 0 { diff --git a/core_commands/kill.go b/core_commands/kill.go index 1016c75..9689bad 100644 --- a/core_commands/kill.go +++ b/core_commands/kill.go @@ -10,7 +10,7 @@ var kill_cmd = &commands.Command{ Name: "kill", RequiredPermissions: []string{"server.command.kill"}, Arguments: []commands.Argument{ - commands.NewEntityArgument("player", commands.EntityPlayerOnly), + commands.NewEntityArg("player", commands.EntityPlayerOnly), }, Execute: func(ctx commands.CommandContext) { var player *server.Session diff --git a/core_commands/msg.go b/core_commands/msg.go index 13d8e91..ae08db1 100644 --- a/core_commands/msg.go +++ b/core_commands/msg.go @@ -12,7 +12,7 @@ var msg_cmd = &commands.Command{ Name: "msg", RequiredPermissions: []string{"server.chat"}, Arguments: []commands.Argument{ - commands.NewEntityArgument("targets", commands.EntitySingle), + commands.NewEntityArg("targets", commands.EntitySingle), commands.NewStrArg("message", commands.GreedyPhrase), }, Execute: func(ctx commands.CommandContext) { diff --git a/core_commands/op.go b/core_commands/op.go index 4f0cf5f..9324b6e 100644 --- a/core_commands/op.go +++ b/core_commands/op.go @@ -8,7 +8,7 @@ var op_cmd = &commands.Command{ Name: "op", RequiredPermissions: []string{"server.command.op"}, Arguments: []commands.Argument{ - commands.NewEntityArgument("player", commands.EntityPlayerOnly), + commands.NewEntityArg("player", commands.EntityPlayerOnly), }, Execute: func(ctx commands.CommandContext) { if len(ctx.Arguments) == 0 { diff --git a/core_commands/summon.go b/core_commands/summon.go index 91e8159..1a73700 100644 --- a/core_commands/summon.go +++ b/core_commands/summon.go @@ -11,8 +11,8 @@ var summon_cmd = &commands.Command{ Aliases: []string{}, RequiredPermissions: []string{"server.command.summon"}, Arguments: []commands.Argument{ - commands.NewResourceKeyArgument("entity", "minecraft:entity_type"), - commands.NewVector3Argument("location"), + commands.NewResourceKeyArg("entity", "minecraft:entity_type"), + commands.NewVector3Arg("location"), }, Execute: func(ctx commands.CommandContext) { if len(ctx.Arguments) < 4 { diff --git a/core_commands/test.go b/core_commands/test.go index 2be470a..47665b6 100644 --- a/core_commands/test.go +++ b/core_commands/test.go @@ -11,17 +11,19 @@ var test_cmd = &commands.Command{ Name: "test", RequiredPermissions: []string{"server.command.test"}, Arguments: []commands.Argument{ + commands.NewVector3Arg("pos1"), commands.NewStrArg("d", commands.SingleWord), commands.NewBoolArg("gay"), - commands.NewFloatArg("f"), - commands.NewVector3Argument("pos"), + commands.NewIntArg("f"), + commands.NewVector3Arg("pos"), }, Execute: func(ctx commands.CommandContext) { + x, y, z, _ := ctx.GetVector3("pos1") d, _ := ctx.GetString("d") gay, _ := ctx.GetBool("gay") - f, _ := ctx.GetFloat64("f") - x, y, z, _ := ctx.GetVector3("pos") + f, _ := ctx.GetInt64("f") + x1, y1, z1, _ := ctx.GetVector3("pos") - ctx.Reply(chat.NewMessage(fmt.Sprintf("%s %v %f %f %f %f", d, gay, f, x, y, z))) + ctx.Reply(chat.NewMessage(fmt.Sprintf("%f %f %f %s %v %d %f %f %f", x, y, z, d, gay, f, x1, y1, z1))) }, } diff --git a/core_commands/tp.go b/core_commands/tp.go index dec817a..f248f4e 100644 --- a/core_commands/tp.go +++ b/core_commands/tp.go @@ -13,8 +13,8 @@ var tp_cmd = &commands.Command{ RequiredPermissions: []string{"server.command.op"}, Aliases: []string{"teleport"}, Arguments: []commands.Argument{ - commands.NewEntityArgument("targets", commands.EntityPlayerOnly), - commands.NewEntityArgument("destination", commands.EntityPlayerOnly).SetAlternative(commands.NewVector3Argument("location")), + commands.NewEntityArg("targets", commands.EntityPlayerOnly), + commands.NewEntityArg("destination", commands.EntityPlayerOnly).SetAlternative(commands.NewVector3Arg("location")), }, Execute: func(ctx commands.CommandContext) { srv := getServer(ctx.Executor) diff --git a/go.mod b/go.mod index 68c77ca..dbab7ee 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( ) require ( - github.com/aimjel/minecraft v0.0.0-20231104165759-5cfa906f9947 + github.com/aimjel/minecraft v0.0.0-20231105145341-243d6972b4d8 github.com/gorilla/websocket v1.5.0 ) diff --git a/go.sum b/go.sum index 388bfb2..8acc4ea 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/aimjel/minecraft v0.0.0-20231102074502-922c6e0af42d h1:12teyvLFC7LHPD github.com/aimjel/minecraft v0.0.0-20231102074502-922c6e0af42d/go.mod h1:jb47g4nDw3J8JdA4WxQpDx25NoIZiyNCjFOtM1b3Urk= github.com/aimjel/minecraft v0.0.0-20231104165759-5cfa906f9947 h1:iDwZHCBcbj3ArSM9MMw8zYIcuM3f31Yifu7ut7V5jg4= github.com/aimjel/minecraft v0.0.0-20231104165759-5cfa906f9947/go.mod h1:jb47g4nDw3J8JdA4WxQpDx25NoIZiyNCjFOtM1b3Urk= +github.com/aimjel/minecraft v0.0.0-20231105145341-243d6972b4d8 h1:NbzK6skaCpdYxZzUIpH1gp5J4qDk6vMm/x+A87uoMeM= +github.com/aimjel/minecraft v0.0.0-20231105145341-243d6972b4d8/go.mod h1:jb47g4nDw3J8JdA4WxQpDx25NoIZiyNCjFOtM1b3Urk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/logger/logger.go b/logger/logger.go index 3d828b1..54ae6e4 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -92,6 +92,8 @@ func ParseChat(msg chat.Message) string { str += color.New(attrs...).SprintFunc()(*text.Text) } + str = strings.ReplaceAll(str, "\n", "\n\r") + return str } @@ -119,6 +121,7 @@ func (logger *Logger) Info(format string, a ...interface{}) { Time: time, Message: str, }) + str = strings.ReplaceAll(str, "\n", "\n\r") if !logger.done { fmt.Printf("\r%s %s: %s\n", GB(time), BB("INFO "), str) fmt.Print("\r> ") @@ -139,6 +142,7 @@ func (logger *Logger) Debug(format string, a ...interface{}) { Time: time, Message: str, }) + str = strings.ReplaceAll(str, "\n", "\n\r") if !logger.done { fmt.Printf("\r%s %s: %s\n", GB(time), CB("DEBUG"), str) fmt.Print("\r> ") @@ -156,6 +160,7 @@ func (logger *Logger) Error(format string, a ...interface{}) { Time: time, Message: str, }) + str = strings.ReplaceAll(str, "\n", "\n\r") if !logger.done { fmt.Fprintf(os.Stderr, "\r%s %s: %s\n", GB(time), RB("ERROR"), str) fmt.Print("\r> ") @@ -173,6 +178,7 @@ func (logger *Logger) Warn(format string, a ...interface{}) { Time: time, Message: str, }) + str = strings.ReplaceAll(str, "\n", "\n\r") if !logger.done { fmt.Printf("\r%s %s: %s\n", GB(time), YB("WARN "), str) fmt.Print("\r> ") diff --git a/main.go b/main.go index 4b104ed..0d492b8 100644 --- a/main.go +++ b/main.go @@ -57,11 +57,7 @@ func start(cfg *server.Config) { var cfg server.Config func main() { - oldState, err := term.MakeRaw(int(os.Stdin.Fd())) - if err != nil { - panic(err) - } - defer term.Restore(int(os.Stdin.Fd()), oldState) + server.OldState, _ = term.MakeRaw(int(os.Stdin.Fd())) log.Info("Starting Dynamite 1.20.1 server") if util.HasArg("-prof") { diff --git a/server/broadcast.go b/server/broadcast.go index b21aaee..a0b3f98 100644 --- a/server/broadcast.go +++ b/server/broadcast.go @@ -7,6 +7,7 @@ import ( "github.com/aimjel/minecraft/chat" "github.com/aimjel/minecraft/protocol/types" + "github.com/dynamitemc/dynamite/server/enum" "github.com/dynamitemc/dynamite/server/item" "github.com/dynamitemc/dynamite/server/registry" "github.com/dynamitemc/dynamite/server/world" @@ -14,6 +15,19 @@ import ( "github.com/aimjel/minecraft/packet" ) +type Vector struct { + X, Y, Z float64 +} + +func (v *Vector) Normalize() { + length := math.Sqrt(v.X*v.X + v.Y*v.Y + v.Z*v.Z) + if length != 0 { + v.X /= length + v.Y /= length + v.Z /= length + } +} + func (srv *Server) GlobalMessage(message chat.Message) { srv.mu.RLock() defer srv.mu.RUnlock() @@ -122,19 +136,38 @@ func positionIsValid(x, y, z float64) bool { !math.IsInf(x, 0) && !math.IsInf(y, 0) && !math.IsInf(z, 0) } -func (p *Session) Hit(entityId int32) { +func cond[T any](c bool, t T, f T) T { + if c { + return t + } else { + return f + } +} + +func (p *Session) Attack(entityId int32) { e := p.Server.FindEntity(entityId) x, y, z := p.Player.Position() soundId := int32(519) if pl, ok := e.(*Session); ok { - if pl.Player.GameMode() == 1 { + if pl.Player.GameMode() == enum.GameModeCreative { return } + x1, y1, z1 := pl.Player.Position() + + x2 := x1 - x + z2 := z1 - z + + v := Vector{x2, y1, z2} + + v.Normalize() + + pl.Push(x1+x2, y1, z1+z2) + health := pl.Player.Health() pl.SetHealth(health - 1) pl.SendPacket(&packet.DamageEvent{ EntityID: entityId, - SourceTypeID: 31, + SourceTypeID: enum.DamageTypePlayerAttack, SourceCauseID: p.entityID + 1, SourceDirectID: p.entityID + 1, SourcePositionX: &x, @@ -147,6 +180,17 @@ func (p *Session) Hit(entityId int32) { if ok { soundId = sound.ProtocolID } + + x1, y1, z1 := entity.data.Pos[0], entity.data.Pos[1], entity.data.Pos[2] + + x2 := x1 - x + z2 := z1 - z + + v := Vector{x2, y1, z2} + + v.Normalize() + + p.Server.SetEntityPosition(entity.ID, x1+x2, y1, z1+z2) } p.Server.mu.RLock() @@ -157,7 +201,7 @@ func (p *Session) Hit(entityId int32) { } pl.SendPacket(&packet.DamageEvent{ EntityID: entityId, - SourceTypeID: 31, + SourceTypeID: enum.DamageTypePlayerAttack, SourceCauseID: p.entityID + 1, SourceDirectID: p.entityID + 1, SourcePositionX: &x, diff --git a/server/chat.go b/server/chat.go index becd392..1a155f3 100644 --- a/server/chat.go +++ b/server/chat.go @@ -7,6 +7,7 @@ import ( "github.com/aimjel/minecraft/chat" "github.com/aimjel/minecraft/packet" + "github.com/dynamitemc/dynamite/server/enum" ) func (p *Session) Chat(pk *packet.ChatMessageServer) { @@ -131,7 +132,7 @@ func (p *Session) Whisper(pl *Session, msg string, timestamp, salt int64, sig [] //MessageSignature: sig, Salt: salt, Timestamp: timestamp, - ChatType: 3, + ChatType: enum.ChatTypeMsgCommandIncoming, NetworkName: chat.NewMessage(prefix + p.Name() + suffix), NetworkTargetName: &tgt, }) diff --git a/server/commands/builders.go b/server/commands/builders.go index 1bbb48f..d8fc4b7 100644 --- a/server/commands/builders.go +++ b/server/commands/builders.go @@ -90,7 +90,7 @@ func NewStrArg(name string, properties stringArgType) Argument { } } -func NewEntityArgument(name string, properties byte) Argument { +func NewEntityArg(name string, properties byte) Argument { props := types.CommandProperties{Flags: properties} return Argument{ Name: name, @@ -101,7 +101,7 @@ func NewEntityArgument(name string, properties byte) Argument { } } -func NewGamemodeArgument(name string) Argument { +func NewGamemodeArg(name string) Argument { return Argument{ Name: name, Parser: Parser{ @@ -110,7 +110,7 @@ func NewGamemodeArgument(name string) Argument { } } -func NewChatComponentArgument(name string) Argument { +func NewChatComponentArg(name string) Argument { return Argument{ Name: name, Parser: Parser{ @@ -119,7 +119,7 @@ func NewChatComponentArgument(name string) Argument { } } -func NewDimensionArgument(name string) Argument { +func NewDimensionArg(name string) Argument { return Argument{ Name: name, Parser: Parser{ @@ -128,7 +128,7 @@ func NewDimensionArgument(name string) Argument { } } -func NewVector3Argument(name string) Argument { +func NewVector3Arg(name string) Argument { return Argument{ Name: name, Parser: Parser{ @@ -137,7 +137,7 @@ func NewVector3Argument(name string) Argument { } } -func NewVector2Argument(name string) Argument { +func NewVector2Arg(name string) Argument { return Argument{ Name: name, Parser: Parser{ @@ -146,7 +146,7 @@ func NewVector2Argument(name string) Argument { } } -func NewResourceKeyArgument(name string, registry string) Argument { +func NewResourceKeyArg(name string, registry string) Argument { return Argument{ Name: name, Parser: Parser{ diff --git a/server/commands/context.go b/server/commands/context.go index b5dacdc..7bc0335 100644 --- a/server/commands/context.go +++ b/server/commands/context.go @@ -21,13 +21,22 @@ type CommandContext struct { } func (ctx CommandContext) GetVector3(name string) (x, y, z float64, ok bool) { - for i, a := range ctx.Arguments { + for i := range ctx.Arguments { + if i >= len(ctx.Command.Arguments) { + continue + } arg := ctx.Command.Arguments[i] if arg.Name == name { if (arg.Parser.ID >= 8 && arg.Parser.ID <= 11) || arg.Parser.ID == 27 { - x1, err1 := strconv.ParseFloat(a, 64) + x1, err1 := strconv.ParseFloat(ctx.Arguments[i], 64) y1, err2 := strconv.ParseFloat(ctx.Arguments[i+1], 64) z1, err3 := strconv.ParseFloat(ctx.Arguments[i+2], 64) + + if name == "pos" { + logger.Println(x1) + logger.Println(y1) + logger.Println(z1) + } if err1 == nil && err2 == nil && err3 == nil { return x1, y1, z1, true } @@ -54,12 +63,14 @@ func (ctx CommandContext) GetVector2(name string) (x, y float64, ok bool) { } func (ctx CommandContext) GetString(name string) (value string, ok bool) { - for i, a := range ctx.Arguments { + ar := make([]string, len(ctx.Arguments)) + copy(ar, ctx.Arguments) + for i, a := range ar { arg := ctx.Command.Arguments[i] if arg.Parser.ID >= 8 && arg.Parser.ID <= 10 { - ctx.Arguments = slices.Delete(ctx.Arguments, i+1, i+3) + ar = slices.Delete(ar, i+1, i+3) } else if arg.Parser.ID == 11 || arg.Parser.ID == 27 { - ctx.Arguments = slices.Delete(ctx.Arguments, i+1, i+2) + ar = slices.Delete(ar, i+1, i+2) } if arg.Name == name { return a, true diff --git a/server/enum/biome.go b/server/enum/biome.go new file mode 100644 index 0000000..42829c8 --- /dev/null +++ b/server/enum/biome.go @@ -0,0 +1,68 @@ +package enum + +const ( + BiomeBadlands int32 = iota + BiomeBambooJungle + BiomeBasaltDeltas + BiomeBeach + BiomeBirchForest + BiomeCherryGrove + BiomeColdOcean + BiomeCrimsonForest + BiomeDarkForest + BiomeDeepColdOcean + BiomeDeepDark + BiomeDeepFrozenOcean + BiomeDeepLukewarmOcean + BiomeDeepOcean + BiomeDesert + BiomeDripstoneCaves + BiomeEndBarrens + BiomeEndHighlands + BiomeEndMidlands + BiomeErodedBadlands + BiomeFlowerForest + BiomeForest + BiomeFrozenOcean + BiomeFrozenPeaks + BiomeFrozenRiver + BiomeGrove + BiomeIceSpikes + BiomeJaggedPeaks + BiomeJungle + BiomeLukewarmOcean + BiomeLushCaves + BiomeMangroveSwamp + BiomeMeadow + BiomeMushroomFields + BiomeNetherWastes + BiomeOcean + BiomeOldGrowthBirchForest + BiomeOldGrowthPineTaiga + BiomeOldGrowthSpruceForest + BiomePlains + BiomeRiver + BiomeSavanna + BiomeSavannaPlateau + BiomeSmallEndIslands + BiomeSnowyBeach + BiomeSnowyPlains + BiomeSnowySlopes + BiomeSnowyTaiga + BiomeSoulSandValley + BiomeSparseJungle + BiomeStonyPeaks + BiomeStonyShore + BiomeSunflowerPlains + BiomeSwamp + BiomeTaiga + BiomeTheEnd + BiomeTheVoid + BiomeWarmOcean + BiomeWarpedForest + BiomeWindsweptForest + BiomeWindsweptGravellyHills + BiomeWindsweptHills + BiomeWindsweptSavanna + BiomeWoodedBadlands +) diff --git a/server/enum/chat_type.go b/server/enum/chat_type.go new file mode 100644 index 0000000..06e96af --- /dev/null +++ b/server/enum/chat_type.go @@ -0,0 +1,11 @@ +package enum + +const ( + ChatTypeRegular int32 = iota + ChatTypeEmoteCommand + ChatTypeMsgCommandIncoming + ChatTypeMsgCommandOutgoing + ChatTypeSayCommand + ChatTypeTeamMsgCommandIncoming + ChatTypeTeamMsgCommandOutgoing +) diff --git a/server/enum/client_command.go b/server/enum/client_command.go new file mode 100644 index 0000000..155bb21 --- /dev/null +++ b/server/enum/client_command.go @@ -0,0 +1,28 @@ +package enum + +const ( + ClientCommandRespawn int32 = iota + ClientCommandRequestStats +) + +const ( + PlayerCommandStartSneaking int32 = iota + PlayerCommandStopSneaking + PlayerCommandLeaveBed + PlayerCommandStartSprinting + PlayerCommandStopSprinting + PlayerCommandStartJumpWithHorse + PlayerCommandStopJumpWithHorse + PlayerCommandOpenHorseInventory + PlayerCommandStartFlyingElytra +) + +const ( + PlayerActionStartedDigging int32 = iota + PlayerActionCancelledDigging + PlayerActionFinishedDigging + PlayerActionDropItemStack + PlayerActionDropItem + PlayerActionShootArrowFinishEating + PlayerActionSwapItemInHand +) diff --git a/server/enum/client_information.go b/server/enum/client_information.go new file mode 100644 index 0000000..1aba4a2 --- /dev/null +++ b/server/enum/client_information.go @@ -0,0 +1,22 @@ +package enum + +const ( + ChatModeEnabled int32 = iota + ChatModeCommandsOnly + ChatModeHidden +) + +const ( + MainHandLeft int32 = iota + MainHandRight +) + +const ( + DisplayedSkinPartCape byte = 0x01 + DisplayedSkinPartJacket byte = 0x02 + DisplayedSkinPartLeftSleeve byte = 0x04 + DisplayedSkinPartRightSleeve byte = 0x08 + DisplayedSkinPartLeftLeg byte = 0x10 + DisplayedSkinPartRightLeg byte = 0x20 + DisplayedSkinPartHat byte = 0x40 +) diff --git a/server/enum/damage_type.go b/server/enum/damage_type.go new file mode 100644 index 0000000..8b51687 --- /dev/null +++ b/server/enum/damage_type.go @@ -0,0 +1,48 @@ +package enum + +const ( + DamageTypeArrow int32 = iota + DamageTypeBedRespawnPoint + DamageTypeCactus + DamageTypeCramming + DamageTypeDragonBreath + DamageTypeDrown + DamageTypeDryOut + DamageTypeExplosion + DamageTypeFall + DamageTypeFallingAnvil + DamageTypeFallingBlock + DamageTypeFallingStalactite + DamageTypeFireball + DamageTypeFireworks + DamageTypeFlyIntoWall + DamageTypeFreeze + DamageTypeGeneric + DamageTypeGenericKill + DamageTypeHotFloor + DamageTypeInFire + DamageTypeInWall + DamageTypeIndirectMagic + DamageTypeLava + DamageTypeLightningBolt + DamageTypeMagic + DamageTypeMobAttack + DamageTypeMobAttackNoAggro + DamageTypeMobProjectile + DamageTypeOnFire + DamageTypeOutOfWorld + DamageTypeOutsideBorder + DamageTypePlayerAttack + DamageTypePlayerExplosion + DamageTypeSonicBoom + DamageTypeStalagmite + DamageTypeStarve + DamageTypeSting + DamageTypeSweetBerryBush + DamageTypeThorns + DamageTypeThrown + DamageTypeTrident + DamageTypeUnattributedFireball + DamageTypeWither + DamageTypeWitherSkull +) diff --git a/server/enum/dimension_type.go b/server/enum/dimension_type.go new file mode 100644 index 0000000..96e6dd8 --- /dev/null +++ b/server/enum/dimension_type.go @@ -0,0 +1,8 @@ +package enum + +const ( + DimensionTypeOverworld int32 = iota + DimensionTypeOverworldCaves + DimensionTypeTheEnd + DimensionTypeTheNether +) diff --git a/server/enum/entity_animation.go b/server/enum/entity_animation.go new file mode 100644 index 0000000..36798ae --- /dev/null +++ b/server/enum/entity_animation.go @@ -0,0 +1,9 @@ +package enum + +const ( + EntityAnimationSwingMainArm byte = iota + EntityAnimationLeaveBed + EntityAnimationSwingOffhand + EntityAnimationCriticalEffect + EntityAnimationMagicCriticalEffect +) diff --git a/server/enum/game_event.go b/server/enum/game_event.go new file mode 100644 index 0000000..0cffcc3 --- /dev/null +++ b/server/enum/game_event.go @@ -0,0 +1,16 @@ +package enum + +const ( + GameEventNoRespawnBlockAvailable byte = iota + GameEventBeginRaining + GameEventEndRaining + GameEventChangeGamemode + GameEventWinGame + GameEventDemoEvent + GameEventArrowHitPlayer + GameEventRainLevelChange + GameEventThunderLevelChange + GameEventPufferfishStingSound + GameEventElderGuardianMobAppearancee + GameEventEnableRespawnScreen +) diff --git a/server/enum/gamemode.go b/server/enum/gamemode.go new file mode 100644 index 0000000..3a2746a --- /dev/null +++ b/server/enum/gamemode.go @@ -0,0 +1,8 @@ +package enum + +const ( + GameModeSurvival byte = iota + GameModeCreative + GameModeAdventure + GameModeSpectator +) diff --git a/server/enum/player_abilities.go b/server/enum/player_abilities.go new file mode 100644 index 0000000..d4bf858 --- /dev/null +++ b/server/enum/player_abilities.go @@ -0,0 +1,8 @@ +package enum + +const ( + PlayerAbilityInvulnerable byte = 0x01 + PlayerAbilityFlying byte = 0x02 + PlayerAbilityAllowFlying byte = 0x04 + PlayerAbilityCreativeMode byte = 0x08 +) diff --git a/server/enum/trim_material.go b/server/enum/trim_material.go new file mode 100644 index 0000000..87de7a1 --- /dev/null +++ b/server/enum/trim_material.go @@ -0,0 +1,14 @@ +package enum + +const ( + TrimMaterialAmethyst int32 = iota + TrimMaterialCopper + TrimMaterialDiamond + TrimMaterialEmerald + TrimMaterialGold + TrimMaterialIron + TrimMaterialLapis + TrimMaterialNetherite + TrimMaterialQuartz + TrimMaterialRedstone +) diff --git a/server/enum/trim_pattern.go b/server/enum/trim_pattern.go new file mode 100644 index 0000000..385abbe --- /dev/null +++ b/server/enum/trim_pattern.go @@ -0,0 +1,20 @@ +package enum + +const ( + TrimPatternCoast int32 = iota + TrimPatternDune + TrimPatternEye + TrimPatternHost + TrimPatternRaiser + TrimPatternRib + TrimPatternSentry + TrimPatternShaper + TrimPatternSilence + TrimPatternSnout + TrimPatternSpire + TrimPatternTide + TrimPatternVex + TrimPatternWard + TrimPatternWayfinder + TrimPatternWild +) diff --git a/server/enum/world_event.go b/server/enum/world_event.go new file mode 100644 index 0000000..38176f6 --- /dev/null +++ b/server/enum/world_event.go @@ -0,0 +1,86 @@ +package enum + +const ( + WorldEventDispenserDispenses int32 = iota + 1000 + WorldEventDispenserDispenseFail + WorldEventDispenserShoots + WorldEventEnderEyeLaunched + WorldEventFireworkShot + WorldEventIronDoorOpened + WorldEventWoodenDoorOpened + WorldEventWoodenTrapdoorOpened + WorldEventFenceGateOpened + WorldEventFireExtinguished + WorldEventPlayRecord + WorldEventIronDoorClosed + WorldEventWoodenDoorClosed + WorldEventWoodenTrapdoorClosed + WorldEventFenceGateClosed + WorldEventGhastWarms + WorldEventGhastShoots + WorldEventEnderdragonShoots + WorldEventBlazeShoots + WorldEventZombieAttacksWoodDoor + WorldEventZombieAttacksIronDoor + WorldEventZombieBreaksWoodDoor + WorldEventWitherBreaksBlock + WorldEventWitherSpawned + WorldEventWitherShoots + WorldEventBatTakesOff + WorldEventZombieInfects + WorldEventZombieVillagerConverted + WorldEventEnderDragonDeath + WorldEventAnvilDestroyed + WorldEventAnvilUsed + WorldEventAnvilLanded + WorldEventPortalTravel + WorldEventChorusFlowerGrown + WorldEventChorusFlowerDied + WorldEventBrewingStandBrewed + WorldEventIronTrapdoorOpened + WorldEventIronTrapdoorClosed + WorldEventEndPortalCreatedInOverworld + WorldEventPhantomBites + WorldEventZombieConvertsToDrowned + WorldEventHuskConvertsToZombie + WorldEventGrindstoneUsed + WorldEventBookPageTurned +) + +const ( + WorldEventComposts int32 = iota + 1500 + WorldEventLavaConvertsBlock + WorldEventRedstoneTorchBurnOut + WorldEventEnderEyePlaced +) + +const ( + WorldEventSmokeParticles int32 = iota + 2000 + WorldEventBlockBreak + WorldEventSplashPotion + WorldEventEyeOfEnderBreakAnimation + WorldEventMobSpawnParticleEffect + WorldEventBonemealParticles + WorldEventDragonBreath + WorldEventInstantSplashPotionEffect + WorldEventEnderDragonDestroysBlock + WorldEventWetSpongeVaporizeNether +) + +const ( + WorldEventEndGatewaySpawn int32 = iota + 3000 + WorldEventEnderDragonGrowl + WorldEventElectricSpark + WorldEventCopperApplyWax + WorldEventCopperRemoveWax + WorldEventCopperScrapeOxidation +) + +const ( + SmokeDirectionDown int32 = iota + SmokeDirectionUp + SmokeDirectionNorth + SmokeDirectionSouth + SmokeDirectionWest + SmokeDirectionEast +) diff --git a/server/network/handlers/arm_swing.go b/server/network/handlers/arm_swing.go index 46d0fef..08ebcfd 100644 --- a/server/network/handlers/arm_swing.go +++ b/server/network/handlers/arm_swing.go @@ -1,9 +1,11 @@ package handlers +import "github.com/dynamitemc/dynamite/server/enum" + func SwingArm(controller Controller, hand int32) { var animation uint8 if hand == 1 { - animation = 3 + animation = enum.EntityAnimationSwingOffhand } controller.BroadcastAnimation(animation) } diff --git a/server/network/handlers/chat_command.go b/server/network/handlers/chat_command.go index e469b75..b3aa6ff 100644 --- a/server/network/handlers/chat_command.go +++ b/server/network/handlers/chat_command.go @@ -7,6 +7,7 @@ import ( "github.com/aimjel/minecraft/chat" "github.com/aimjel/minecraft/packet" "github.com/dynamitemc/dynamite/logger" + "github.com/dynamitemc/dynamite/server/block" "github.com/dynamitemc/dynamite/server/commands" ) @@ -18,7 +19,7 @@ type Controller interface { HandleCenterChunk(x1, z1, x2, z2 float64) BroadcastPose(pose int32) BroadcastSprinting(val bool) - Hit(entityId int32) + Attack(entityId int32) BroadcastAnimation(animation uint8) SendCommandSuggestionsResponse(id int32, start int32, length int32, matches []packet.SuggestionMatch) BroadcastSkinData() @@ -33,6 +34,7 @@ type Controller interface { Name() string IP() string ClearItem(slot int8) + OnBlock() block.Block } func ChatCommandPacket(controller Controller, graph *commands.Graph, log *logger.Logger, content string, timestamp, salt int64, sigs []packet.Argument) { diff --git a/server/network/handlers/client_command.go b/server/network/handlers/client_command.go index c33db7f..52b2515 100644 --- a/server/network/handlers/client_command.go +++ b/server/network/handlers/client_command.go @@ -1,12 +1,13 @@ package handlers import ( + "github.com/dynamitemc/dynamite/server/enum" "github.com/dynamitemc/dynamite/server/player" ) func ClientCommand(controller Controller, state *player.Player, action int32) { switch action { - case 0: + case enum.ClientCommandRespawn: { controller.Respawn(state.Dimension()) } diff --git a/server/network/handlers/player_abilities.go b/server/network/handlers/player_abilities.go index 1878a2b..06847e0 100644 --- a/server/network/handlers/player_abilities.go +++ b/server/network/handlers/player_abilities.go @@ -1,9 +1,10 @@ package handlers import ( + "github.com/dynamitemc/dynamite/server/enum" "github.com/dynamitemc/dynamite/server/player" ) func PlayerAbilities(state *player.Player, flags byte) { - state.SetFlying(flags == 0x02) + state.SetFlying(flags == enum.PlayerAbilityFlying) } diff --git a/server/network/handlers/player_action.go b/server/network/handlers/player_action.go index c0d8989..726ec84 100644 --- a/server/network/handlers/player_action.go +++ b/server/network/handlers/player_action.go @@ -2,20 +2,21 @@ package handlers import ( "github.com/aimjel/minecraft/packet" + "github.com/dynamitemc/dynamite/server/enum" "github.com/dynamitemc/dynamite/server/player" ) func PlayerAction(controller Controller, state *player.Player, pk *packet.PlayerActionServer) { switch pk.Status { - case 0: + case enum.PlayerActionStartedDigging: controller.BroadcastPose(14) //go controller.BroadcastDigging(pk.Location) - case 1, 2: + case enum.PlayerActionCancelledDigging, enum.PlayerActionFinishedDigging: if pk.Status == 2 { controller.BreakBlock(pk.Location) } controller.BroadcastPose(0) - case 3, 4: + case enum.PlayerActionDropItemStack, enum.PlayerActionDropItem: if s, ok := state.Inventory().HeldItem(); ok { state.SetPreviousSelectedSlot(s) state.Inventory().DeleteSlot(int8(s.Slot)) diff --git a/server/network/handlers/player_command.go b/server/network/handlers/player_command.go index f29514a..9571bc8 100644 --- a/server/network/handlers/player_command.go +++ b/server/network/handlers/player_command.go @@ -1,20 +1,27 @@ package handlers +import "github.com/dynamitemc/dynamite/server/enum" + func PlayerCommand(controller Controller, action int32) { switch action { - case 0: + case enum.PlayerCommandStartSneaking: // start sneaking / swimming { - controller.BroadcastPose(5) + b := controller.OnBlock() + if b.EncodedName() == "minecraft:water" { + controller.BroadcastPose(3) + } else { + controller.BroadcastPose(5) + } } - case 1: + case enum.PlayerCommandStopSneaking: // stop sneaking / swimming { controller.BroadcastPose(0) } - case 3: + case enum.PlayerCommandStartSprinting: // sprint { controller.BroadcastSprinting(true) } - case 4: + case enum.PlayerCommandStopSprinting: // stop sprint { controller.BroadcastSprinting(false) } diff --git a/server/network/handlers/player_interact.go b/server/network/handlers/player_interact.go index 7ff25fd..94deb64 100644 --- a/server/network/handlers/player_interact.go +++ b/server/network/handlers/player_interact.go @@ -4,6 +4,6 @@ import "github.com/aimjel/minecraft/packet" func Interact(controller Controller, pk *packet.InteractServer) { if pk.Type == 1 { - controller.Hit(pk.EntityID) + controller.Attack(pk.EntityID) } } diff --git a/server/network/handlers/set_creative_mode_slot.go b/server/network/handlers/set_creative_mode_slot.go index e30fd1c..67a95d1 100644 --- a/server/network/handlers/set_creative_mode_slot.go +++ b/server/network/handlers/set_creative_mode_slot.go @@ -3,13 +3,14 @@ package handlers import ( "github.com/aimjel/minecraft/chat" "github.com/aimjel/minecraft/packet" + "github.com/dynamitemc/dynamite/server/enum" "github.com/dynamitemc/dynamite/server/inventory" "github.com/dynamitemc/dynamite/server/item" "github.com/dynamitemc/dynamite/server/player" ) func SetCreativeModeSlot(controller Controller, state *player.Player, slot int16, data packet.Slot) { - if state.GameMode() != 1 { + if state.GameMode() != enum.GameModeCreative { controller.Disconnect(chat.NewMessage("bruh cant use de creative button without creative")) return } diff --git a/server/network/handlers/teleport_to_entity.go b/server/network/handlers/teleport_to_entity.go index 0e53559..ba8d15c 100644 --- a/server/network/handlers/teleport_to_entity.go +++ b/server/network/handlers/teleport_to_entity.go @@ -2,11 +2,12 @@ package handlers import ( "github.com/aimjel/minecraft/chat" + "github.com/dynamitemc/dynamite/server/enum" "github.com/dynamitemc/dynamite/server/player" ) func TeleportToEntity(controller Controller, state *player.Player, uuid [16]byte) { - if state.GameMode() != 3 { + if state.GameMode() != enum.GameModeSpectator { controller.Disconnect(chat.NewMessage("Yo how do you do dat without gamemode spectator?")) return } diff --git a/server/server.go b/server/server.go index b232bde..19dba74 100644 --- a/server/server.go +++ b/server/server.go @@ -10,6 +10,7 @@ import ( "sync/atomic" "github.com/dynamitemc/dynamite/server/permission" + "golang.org/x/term" "github.com/aimjel/minecraft/chat" "github.com/aimjel/minecraft/protocol/types" @@ -293,6 +294,7 @@ func (srv *Server) Close() { f, _ := os.OpenFile("config.toml", os.O_RDWR|os.O_CREATE, 0666) _ = toml.NewEncoder(f).Encode(srv.Config) + term.Restore(int(os.Stdin.Fd()), OldState) os.Exit(0) } @@ -331,3 +333,5 @@ func (srv *Server) ConsoleCommand(txt string) { type ConsoleExecutor struct { Server *Server } + +var OldState *term.State diff --git a/server/session.go b/server/session.go index 8c6027b..06fb97d 100644 --- a/server/session.go +++ b/server/session.go @@ -5,13 +5,16 @@ import ( "encoding/base64" "encoding/json" "fmt" - "github.com/dynamitemc/dynamite/server/permission" "math" "math/rand" "slices" "sync" "time" + "github.com/dynamitemc/dynamite/server/block" + "github.com/dynamitemc/dynamite/server/enum" + "github.com/dynamitemc/dynamite/server/permission" + "github.com/aimjel/minecraft/chat" "github.com/aimjel/minecraft/protocol/types" "github.com/google/uuid" @@ -25,7 +28,6 @@ import ( "github.com/aimjel/minecraft/packet" "github.com/dynamitemc/dynamite/server/commands" "github.com/dynamitemc/dynamite/server/player" - "github.com/dynamitemc/dynamite/server/registry" "github.com/dynamitemc/dynamite/server/world" ) @@ -241,7 +243,7 @@ func (p *Session) Login(dim string) { abs := p.Player.SavedAbilities() abps := &packet.PlayerAbilities{FlyingSpeed: abs.FlySpeed, FieldOfViewModifier: 0.1} if abs.Flying != 0 { - abps.Flags |= 0x06 + abps.Flags |= enum.PlayerAbilityFlying | enum.PlayerAbilityAllowFlying } if abps.Flags != 0 { p.SendPacket(abps) @@ -296,7 +298,7 @@ func (p *Session) Kill(message string) { p.BroadcastHealth() if f, _ := world.GameRule(p.Server.World.Gamerules()["doImmediateRespawn"]).Bool(); !f { p.SendPacket(&packet.GameEvent{ - Event: 11, + Event: uint8(enum.GameEventEnableRespawnScreen), Value: 0, }) } @@ -308,7 +310,7 @@ func (p *Session) Kill(message string) { } pl.SendPacket(&packet.DamageEvent{ EntityID: p.entityID, - SourceTypeID: 17, + SourceTypeID: int32(enum.DamageTypeGenericKill), }) pl.SendPacket(&packet.EntityEvent{ EntityID: p.entityID, @@ -319,7 +321,7 @@ func (p *Session) Kill(message string) { p.SendPacket(&packet.DamageEvent{ EntityID: p.entityID, - SourceTypeID: 17, + SourceTypeID: int32(enum.DamageTypeGenericKill), }) p.Despawn() p.SendPacket(&packet.CombatDeath{ @@ -360,27 +362,26 @@ func (p *Session) SetSessionID(id [16]byte, pk, ks []byte, expires int64) { func (p *Session) SetGameMode(gm byte) { p.Player.SetGameMode(gm) p.SendPacket(&packet.GameEvent{ - Event: 3, + Event: enum.GameEventChangeGamemode, Value: float32(gm), }) p.BroadcastGamemode() } -/* - func (p *Session) Push(x, y, z float64) { - yaw, pitch := p.Player.Rotation() - p.Player.SetPosition(x, y, z, yaw, pitch, p.Player.OnGround()) - p.SendPacket(&packet.PlayerPositionLook{ - X: x, - Y: y, - Z: z, - Yaw: yaw, - Pitch: pitch, - TeleportID: idCounter.Add(1), - }) - p.BroadcastMovement(0, x, y, z, yaw, pitch, p.Player.OnGround(), true) - } -*/ +func (p *Session) Push(x, y, z float64) { + yaw, pitch := p.Player.Rotation() + p.Player.SetPosition(x, y, z, yaw, pitch, p.Player.OnGround()) + p.SendPacket(&packet.PlayerPositionLook{ + X: x, + Y: y, + Z: z, + Yaw: yaw, + Pitch: pitch, + TeleportID: idCounter.Add(1), + }) + p.BroadcastMovement(0, x, y, z, yaw, pitch, p.Player.OnGround(), true) +} + func (p *Session) Teleport(x, y, z float64, yaw, pitch float32) { p.Player.SetPosition(x, y, z, yaw, pitch, p.Player.OnGround()) p.SendPacket(&packet.PlayerPositionLook{ @@ -454,7 +455,7 @@ func (p *Session) SendChunks(dimension *world.Dimension) { p.loadedChunks[[2]int32{x, z}] = struct{}{} p.SendPacket(c.Data()) - for _, en := range c.Entities { + /*for _, en := range c.Entities { u, _ := world.IntUUIDToByteUUID(en.UUID) var e *Entity @@ -486,7 +487,7 @@ func (p *Session) SendChunks(dimension *world.Dimension) { Type: t.ProtocolID, }) p.spawnedEntities = append(p.spawnedEntities, e.ID) - } + }*/ } } } @@ -678,6 +679,11 @@ func (p *Session) SetDisplayName(name string) { } } +func (p *Session) OnBlock() block.Block { + x, y, z := p.Player.Position() + return p.Server.GetDimension(p.Player.Dimension()).Block(int64(x), int64(y-1), int64(z)) +} + func (p *Session) TeleportToEntity(uuid [16]byte) { e := p.Server.FindEntityByUUID(uuid) if e == nil { diff --git a/server/tick.go b/server/tick.go index 24bb042..acb5d36 100644 --- a/server/tick.go +++ b/server/tick.go @@ -19,8 +19,6 @@ func (srv *Server) tick(tick uint) { e.Entity.Tick(srv, tick) } for _, pl := range srv.players { - //x, y, z := pl.Player.Position() - //srv.SpawnEntity("minecraft:enderman", x, y, z) //if tick%8 == 0 { //pl.SendChunks(srv.GetDimension(pl.Player.Dimension())) //pl.UnloadChunks()