diff --git a/core_commands/commands.go b/core_commands/commands.go index c823c6b..dc11bee 100644 --- a/core_commands/commands.go +++ b/core_commands/commands.go @@ -6,5 +6,6 @@ var Commands = &commands.Graph{ Commands: []*commands.Command{ test_cmd, reload_cmd, + gamemode_cmd, }, } diff --git a/core_commands/gamemode.go b/core_commands/gamemode.go new file mode 100644 index 0000000..22c3c4a --- /dev/null +++ b/core_commands/gamemode.go @@ -0,0 +1,72 @@ +package core_commands + +import ( + "fmt" + "strings" + + "github.com/dynamitemc/dynamite/server" + "github.com/dynamitemc/dynamite/server/commands" + p "github.com/dynamitemc/dynamite/server/player" +) + +func pascalify(str string) (res string) { + sp := strings.Split(str, " ") + for _, w := range sp { + spp := strings.Split(w, "") + res += strings.ToUpper(spp[0]) + strings.ToLower(strings.Join(spp[1:], "")) + } + return +} + +var gamemode_cmd = &commands.Command{ + Name: "gamemode", + RequiredPermissions: []string{"server.command.gamemode"}, + Arguments: []commands.Argument{ + { + Name: "mode", + ParserID: 39, + }, + { + Name: "player", + ParserID: 6, + Properties: commands.Properties{ + Flags: 0x02, + }, + }, + }, + Execute: func(ctx commands.CommandContext) { + if len(ctx.Arguments) == 0 { + ctx.Incomplete() + return + } + gm := p.Gamemode(ctx.Arguments[0]) + if gm == -1 { + ctx.ErrorAt(fmt.Sprintf("Unknown game mode: %s", ctx.Arguments[0])) + return + } + var player *server.PlayerController + if len(ctx.Arguments) == 1 { + if ctx.IsConsole { + ctx.Incomplete() + return + } + player = ctx.Executor.(*server.PlayerController) + } else { + p, ok := ctx.Executor.(*server.PlayerController).Server.Players[ctx.Arguments[1]] + if !ok { + ctx.Error("No player was found") + return + } + player = p + } + if player.GameMode() == byte(gm) { + return + } + player.SetGameMode(byte(gm)) + msg := fmt.Sprintf("Set %s's game mode to %s Mode", player.Name(), pascalify(ctx.Arguments[0])) + if player.UUID == ctx.Executor.(*server.PlayerController).UUID { + msg = fmt.Sprintf("Set own game mode to %s Mode", pascalify(ctx.Arguments[0])) + } + ctx.Reply(msg) + }, +} diff --git a/core_commands/reload.go b/core_commands/reload.go index 952a863..d5e3015 100644 --- a/core_commands/reload.go +++ b/core_commands/reload.go @@ -8,7 +8,7 @@ import ( var reload_cmd = &commands.Command{ Name: "reload", Aliases: []string{"rl"}, - RequiredPermissions: []string{"server.reload"}, + RequiredPermissions: []string{"server.command.reload"}, Execute: func(ctx commands.CommandContext) { srv := ctx.Executor.(*server.PlayerController).Server srv.Reload() diff --git a/go.mod b/go.mod index b4fe7d8..1b8d241 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( require ( github.com/Shopify/go-lua v0.0.0-20221004153744-91867de107cf - github.com/aimjel/minecraft v0.0.0-20230913195637-f88fef694bb7 + github.com/aimjel/minecraft v0.0.0-20230927182639-1fa3dd7aeebc github.com/dop251/goja v0.0.0-20230919151941-fc55792775de ) diff --git a/go.sum b/go.sum index 9b92665..460ae7b 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,12 @@ github.com/Shopify/go-lua v0.0.0-20221004153744-91867de107cf h1:VSUCKpFV0AfYGslg github.com/Shopify/go-lua v0.0.0-20221004153744-91867de107cf/go.mod h1:UCCi6u6YA8oXfJ15vEMiMGIaWWfLiOacinBPHxLXtEU= github.com/aimjel/minecraft v0.0.0-20230913195637-f88fef694bb7 h1:XPhfvCmyVpja/BJvhZZ20LL3XrBNQsdhCp4SX2Y/woQ= github.com/aimjel/minecraft v0.0.0-20230913195637-f88fef694bb7/go.mod h1:/Y9/YBqxNOU7IFInEjDbsCVkdPNYJCPxC26jK+w3Phc= +github.com/aimjel/minecraft v0.0.0-20230927150952-b10c2a7b1397 h1:vb08EgkegNGu03fxYG2fxmj2F6E4fNrFqY1PGLWr9SM= +github.com/aimjel/minecraft v0.0.0-20230927150952-b10c2a7b1397/go.mod h1:/Y9/YBqxNOU7IFInEjDbsCVkdPNYJCPxC26jK+w3Phc= +github.com/aimjel/minecraft v0.0.0-20230927163915-b3907034c0a8 h1:Vl58C0lpKTDgSZJivqU1AynKQXPQ2vR2+72pz1iIFFI= +github.com/aimjel/minecraft v0.0.0-20230927163915-b3907034c0a8/go.mod h1:/Y9/YBqxNOU7IFInEjDbsCVkdPNYJCPxC26jK+w3Phc= +github.com/aimjel/minecraft v0.0.0-20230927182639-1fa3dd7aeebc h1:irjh4/oH9vWvkOr8xyQGudFeOYVpuzy9dgDnTkevtvg= +github.com/aimjel/minecraft v0.0.0-20230927182639-1fa3dd7aeebc/go.mod h1:/Y9/YBqxNOU7IFInEjDbsCVkdPNYJCPxC26jK+w3Phc= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= diff --git a/main.go b/main.go index a061eb7..0c9b30f 100644 --- a/main.go +++ b/main.go @@ -38,6 +38,11 @@ func main() { var cfg server.ServerConfig config.LoadConfig("config.toml", &cfg) log.Debug("Loaded config") + + if !cfg.Online && !util.HasArg("-no_offline_warn") { + log.Warn("Offline mode is insecure and you should not use it unless for a private server.") + } + if cfg.Web.Enable { if !util.HasArg("-nogui") { go web.LaunchWebPanel(fmt.Sprintf("%s:%d", cfg.Web.ServerIP, cfg.Web.ServerPort), cfg.Web.Password, &log) diff --git a/server/commands/commands.go b/server/commands/commands.go index 699ee59..84feaf2 100644 --- a/server/commands/commands.go +++ b/server/commands/commands.go @@ -15,9 +15,11 @@ type CommandContext struct { ClientSettings() player.ClientInformation Position() (x float64, y float64, z float64) Rotation() (yaw float32, pitch float32) + HasPermissions(perms []string) bool } `js:"executor"` Arguments []string `js:"arguments"` - FullCommand string + FullCommand string `js:"fullCommand"` + IsConsole bool `js:"isConsole"` } func (ctx *CommandContext) Reply(content string) { @@ -28,9 +30,13 @@ func (ctx *CommandContext) Incomplete() { ctx.Reply(fmt.Sprintf("§cUnknown or incomplete command, see below for error\n§7%s§r§c§o<--[HERE]", ctx.FullCommand)) } -func (ctx *CommandContext) Error(msg string) { +func (ctx *CommandContext) ErrorAt(msg string) { sp := strings.Split(ctx.FullCommand, " ") - ctx.Reply(fmt.Sprintf("§c%s\n§7%s§c§n%s§c§o<--[HERE]", msg, strings.Join(sp[:len(sp)-1], " "), sp[len(sp)-1])) + ctx.Reply(fmt.Sprintf("§c%s\n§7%s §c§n%s§c§o<--[HERE]", msg, strings.Join(sp[:len(sp)-1], " "), sp[len(sp)-1])) +} + +func (ctx *CommandContext) Error(msg string) { + ctx.Reply("§c" + msg) } const ( @@ -82,6 +88,9 @@ func (graph Graph) Data() *pk.DeclareCommands { commands := graph.Commands rootChildren := []int32{} for _, command := range commands { + if command == nil { + continue + } for _, alias := range command.Aliases { commands = append(commands, &Command{ Name: alias, @@ -90,13 +99,16 @@ func (graph Graph) Data() *pk.DeclareCommands { } } for _, command := range commands { + if command == nil { + continue + } rootChildren = append(rootChildren, int32(len(packet.Nodes))) - parent := len(packet.Nodes) packet.Nodes = append(packet.Nodes, pk.Node{ Name: command.Name, Flags: 1, }) for _, argument := range command.Arguments { + parent := len(packet.Nodes) - 1 packet.Nodes[parent].Children = append(packet.Nodes[parent].Children, int32(len(packet.Nodes))) node := pk.Node{Flags: 2, Name: argument.Name, Properties: argument.Properties, ParserID: argument.ParserID} if argument.SuggestionType != "" { diff --git a/server/network/handlers/ChatCommand.go b/server/network/handlers/ChatCommand.go index b0a69ed..dd3ba5a 100644 --- a/server/network/handlers/ChatCommand.go +++ b/server/network/handlers/ChatCommand.go @@ -14,6 +14,7 @@ type controller interface { ClientSettings() player.ClientInformation Position() (x float64, y float64, z float64) Rotation() (yaw float32, pitch float32) + HasPermissions(perms []string) bool } func ChatCommandPacket(controller controller, graph *commands.Graph, content string) { @@ -21,6 +22,9 @@ func ChatCommandPacket(controller controller, graph *commands.Graph, content str cmd := args[0] var command *commands.Command for _, c := range graph.Commands { + if c == nil { + continue + } if c.Name == cmd { command = c } @@ -31,12 +35,12 @@ func ChatCommandPacket(controller controller, graph *commands.Graph, content str } } } - if command == nil { + if command == nil || !controller.HasPermissions(command.RequiredPermissions) { controller.SystemChatMessage(fmt.Sprintf("§cUnknown or incomplete command, see below for error\n§n%s§r§c§o<--[HERE]", content)) return } command.Execute(commands.CommandContext{ - Arguments: args, + Arguments: args[1:], Executor: controller, FullCommand: content, }) diff --git a/server/player_controller.go b/server/player_controller.go index d583aec..1d9f5c8 100644 --- a/server/player_controller.go +++ b/server/player_controller.go @@ -1,8 +1,6 @@ package server import ( - "slices" - "github.com/aimjel/minecraft/packet" "github.com/dynamitemc/dynamite/server/commands" "github.com/dynamitemc/dynamite/server/player" @@ -17,9 +15,13 @@ type PlayerController struct { UUID string } +func (p *PlayerController) Name() string { + return p.session.conn.Info.Name +} + func (p *PlayerController) JoinDimension(d *world.Dimension) error { if err := p.session.SendPacket(&packet.JoinGame{ - EntityID: p.player.EntityID, //TODO + EntityID: p.player.EntityID, IsHardcore: p.player.IsHardcore(), GameMode: p.player.GameMode(), PreviousGameMode: p.player.PreviousGameMode(), @@ -61,8 +63,10 @@ func (p *PlayerController) GameMode() byte { } func (p *PlayerController) SetGameMode(gm byte) { - // TO BE IMPLEMENTED - //p.session.SendPacket() + p.session.SendPacket(&packet.GameEvent{ + Event: 3, + Value: float32(gm), + }) } func (p *PlayerController) Teleport(x, y, z float64, yaw, pitch float32) { @@ -80,7 +84,8 @@ func (p *PlayerController) Teleport(x, y, z float64, yaw, pitch float32) { func (p *PlayerController) SendCommands(graph *commands.Graph) { for i, command := range graph.Commands { if !p.HasPermissions(command.RequiredPermissions) { - graph.Commands = slices.Delete(graph.Commands, i, i+1) + //graph.Commands = slices.Delete(graph.Commands, i-1, i) + graph.Commands[i] = nil } } p.session.SendPacket(graph.Data()) diff --git a/server/plugins/plugins-lua.go b/server/plugins/plugins-lua.go index 0471ca5..c978142 100644 --- a/server/plugins/plugins-lua.go +++ b/server/plugins/plugins-lua.go @@ -1,7 +1,6 @@ package plugins import ( - "fmt" "os" "slices" @@ -190,7 +189,6 @@ func GetLuaVM(srv interface { l.SetGlobal("server") luaCreateGlobalFunction(l, "Plugin", func(state *lua.State) int { - fmt.Println("h") if state.IsTable(1) { l.Field(1, "identifier") identifier, ok := l.ToString(-1) diff --git a/server/server.go b/server/server.go index 99d7420..17c06fa 100644 --- a/server/server.go +++ b/server/server.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/aimjel/minecraft" + //"github.com/dynamitemc/dynamite/web" "github.com/dynamitemc/dynamite/logger" "github.com/dynamitemc/dynamite/server/commands" @@ -80,10 +81,9 @@ func (srv *Server) handleNewConn(conn *minecraft.Conn) { srv.addPlayer(cntrl) if err := sesh.HandlePackets(cntrl); err != nil { - u := cntrl.UUID - - srv.Logger.Info("[%s] Player %s (%s) has left the server", conn.RemoteAddr().String(), conn.Info.Name, u) + srv.Logger.Info("[%s] Player %s (%s) has left the server", conn.RemoteAddr().String(), conn.Info.Name, cntrl.UUID) srv.PlayerlistRemove(conn.Info.UUID) + delete(srv.Players, cntrl.UUID) //gui.RemovePlayer(cntrl.UUID) } } diff --git a/server/world/world.go b/server/world/world.go index 59cef24..fb5f482 100644 --- a/server/world/world.go +++ b/server/world/world.go @@ -15,7 +15,7 @@ type worldData struct { Seed int64 `nbt:"seed"` } DataVersion int32 - GameRules map[string]string + GameRules map[string]interface{} } }