diff options
| -rw-r--r-- | server/commands.go | 59 | ||||
| -rw-r--r-- | server/player.go | 1 | ||||
| -rw-r--r-- | server/server.go | 34 |
3 files changed, 93 insertions, 1 deletions
diff --git a/server/commands.go b/server/commands.go index 4e544ce..804be0d 100644 --- a/server/commands.go +++ b/server/commands.go @@ -1,6 +1,7 @@ package server import ( + "io" "fmt" "sort" "strconv" @@ -195,6 +196,50 @@ var commands = map[string]commandHandler { } return "" }, + "kick": func(ctx commandCtx) string { + name, ok := ctx.arg.nextArg() + if !ok { + return usage("kick") + } + arg, _ := io.ReadAll(ctx.arg.rd) + reason := strings.TrimSpace(string(arg)) + if reason != "" { + reason = "Kicked: " + reason + } + if ctx.server.kick(name, string(reason)) { + ctx.sender.OnCommandOutput(ctx.server, + fmt.Sprintf("Kicked %s.", name), + ) + } else { + return "Unknown player: " + name + } + return "" + }, + "ban": func(ctx commandCtx) string { + name, ok := ctx.arg.nextArg() + if !ok { + return usage("ban") + } + arg, _ := io.ReadAll(ctx.arg.rd) + reason := strings.TrimSpace(string(arg)) + if reason != "" { + reason = "Banned: " + reason + } + ctx.server.ban(name, string(reason)) + ctx.sender.OnCommandOutput(ctx.server, fmt.Sprintf("Banned %s.", name)) + return "" + }, + "unban": func(ctx commandCtx) string { + name, ok := ctx.arg.nextArg() + if !ok { + return usage("unban") + } + ctx.server.unban(name) + ctx.sender.OnCommandOutput(ctx.server, + fmt.Sprintf("Unbanned %s.", name), + ) + return "" + }, "op": func(ctx commandCtx) string { name, ok := ctx.arg.nextArg() if !ok { @@ -267,6 +312,8 @@ var commands = map[string]commandHandler { var commandAuth = map[string]authLevel { "tp": cheatAuth, + "kick": moderateAuth, + "ban": moderateAuth, "createLevel": opAuth, "op": opAuth, "deop": opAuth, @@ -291,6 +338,18 @@ var help = map[string][]string { "* --gen: Level generation type (flat, empty)", "* --size: Level dimensions", }, + "kick": []string { + "/kick <player> [reason]", + "Disconnect a player from the server", + }, + "ban": []string { + "/ban <player> [reason]", + "Ban a player from joining the server", + }, + "unban": []string { + "/unban <player> [reason]", + "Unban a player from joining the server", + }, "op": []string { "/op <player>", "Grant operator status", diff --git a/server/player.go b/server/player.go index 6b03466..9904bbe 100644 --- a/server/player.go +++ b/server/player.go @@ -31,6 +31,7 @@ type playerState struct { const ( defaultAuth = 0 cheatAuth = 100 + moderateAuth = 150 opAuth = 200 ConsoleAuth = 900 ) diff --git a/server/server.go b/server/server.go index c549122..b747b14 100644 --- a/server/server.go +++ b/server/server.go @@ -34,6 +34,7 @@ type worldState struct { LastId levelId SpawnLevel levelId SpawnPos entityPos + Banned map[string]string } func NewServer(info ServerInfo) *Server { @@ -66,6 +67,9 @@ func NewServer(info ServerInfo) *Server { }) s.worldState = <-loaded } + if s.worldState.Banned == nil { + s.worldState.Banned = make(map[string]string) + } return s } @@ -179,11 +183,11 @@ func (s *Server) OnDisconnect(cl *client, username string, pl *player) { } if s.players[username] == pl { delete(s.players, username) + s.Broadcast(nil, fmt.Sprintf("&e%s has left", username)) } if username == "" { return } - s.Broadcast(nil, fmt.Sprintf("&e%s has left", username)) }) } @@ -250,9 +254,37 @@ func (s *Server) changePlayerAuth( }) } +func (s *Server) ban(playerName string, reason string) { + log.Printf("banning %s for '%s'", playerName, reason) + s.kick(playerName, reason) + s.worldState.Banned[playerName] = reason +} + +func (s *Server) unban(playerName string) { + log.Printf("unbanning %s", playerName) + delete(s.worldState.Banned, playerName) +} + +func (s *Server) kick(playerName string, reason string) bool { + pl := s.players[playerName] + if pl == nil { + return false + } + if reason == "" { + reason = "Bye!" + } + pl.Kick(s, reason) + return true +} + func (s *Server) NewPlayer( from phony.Actor, cl *client, name string, reply func(*player)) { s.Act(from, func() { + banReason, ok := s.worldState.Banned[name] + if ok { + cl.Disconnect(s, banReason) + return + } s.Broadcast(nil, fmt.Sprintf("&e%s has joined", name)) if s.players[name] != nil { s.players[name].Act(s, func() { |
