diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | cmd/metronode/main.go | 91 | ||||
| -rw-r--r-- | cmd/metronode/texture_server.go | 18 | ||||
| -rw-r--r-- | server/player.go | 8 | ||||
| -rw-r--r-- | server/server.go | 8 | ||||
| m--------- | textures | 0 |
7 files changed, 114 insertions, 15 deletions
@@ -1,3 +1,4 @@ /world /metronode +/textures.zip __debug* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..528b960 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "textures"] + path = textures + url = ../texturepack diff --git a/cmd/metronode/main.go b/cmd/metronode/main.go index 70ded57..bf1cc98 100644 --- a/cmd/metronode/main.go +++ b/cmd/metronode/main.go @@ -2,8 +2,11 @@ package main import ( "os" + "io" "net" + "fmt" "log" + "flag" "bufio" "strings" "sync/atomic" @@ -11,22 +14,70 @@ import ( "git.citrons.xyz/metronode/server" ) +func usage() { + fmt.Fprintf(os.Stderr, "usage: %s [options...] hostname", os.Args[0]) +} + func main() { defer os.Exit(0) + + flag.Usage = func() { + usage() + flag.PrintDefaults() + } + + address := flag.String("listen", ":25565", "port/address to listen on") + httpAddress := flag.String( + "listen-http", ":25599", "port/address for texture HTTP server", + ) + texturePack := flag.String( + "textures-file", "./textures.zip", + "path to textures.zip on disk (not a URL)", + ) + flag.Parse() + + args := flag.Args() + if len(args) < 1 { + fmt.Fprintf(os.Stderr, "error: please specific server hostname") + usage() + os.Exit(1) + } + hostname := args[0] + + var ( + hLn, ln net.Listener + cons console + err error + ) + + _, port, _ := net.SplitHostPort(*httpAddress) + texturesUrl := fmt.Sprintf("http://%s:%s/textures.zip", hostname, port) + s := server.NewServer(server.ServerInfo { Name: "Metronode", Motd: "-hax", + TexturePack: texturesUrl, }) - ln, err := net.Listen("tcp", ":25565") + + cons, err = initConsole() + if err == nil { + defer cons.Close() + log.SetOutput(&cons) + go readConsole(s, &cons) + } else { + log.Print("not using console:", err) + } + + hLn, err = net.Listen("tcp", *httpAddress) if err != nil { log.Fatal(err) } + go run_texture_server(hLn, *texturePack) - cons := initConsole() - defer cons.Close() - log.SetOutput(&cons) - go readConsole(s, &cons) - + ln, err = net.Listen("tcp", *address) + if err != nil { + log.Fatal(err) + } s.Serve(ln) } @@ -53,21 +104,29 @@ type console struct { termState *term.State } -func initConsole() console { - var (c console; input string) - c.input.Store(&input) - c.termState, _ = term.MakeRaw(int(os.Stdin.Fd())) - c.showInput() - return c +func initConsole() (cons console, err error) { + var input string + cons.input.Store(&input) + cons.termState, err = term.MakeRaw(int(os.Stdin.Fd())) + if err != nil { + return + } + cons.showInput() + return } func (c *console) Close() error { + c.input.Store(nil) term.Restore(int(os.Stdin.Fd()), c.termState) os.Stdout.Write([]byte("\n")) return nil } func (c *console) Read(p []byte) (n int, err error) { + input := c.input.Load() + if input == nil { + return 0, io.EOF + } n, err = os.Stdin.Read(p) if err != nil { return @@ -87,7 +146,7 @@ func (c *console) Read(p []byte) (n int, err error) { s = s[newline + 1:] c.input.Store(&s) } else { - s = *c.input.Load() + s + s = *input + s c.input.Store(&s) } c.Write([]byte{}) @@ -95,12 +154,16 @@ func (c *console) Read(p []byte) (n int, err error) { } func (c *console) showInput() { + input := c.input.Load() + if input == nil { + return + } s := "\0337" // save cursor position w, _, _ := term.GetSize(int(os.Stdout.Fd())) s = s + strings.Repeat(" ", w) s = s + "\0338" // restore s = s + "\0337" // save - s = s + "> " + *c.input.Load() + s = s + "> " + *input os.Stdout.Write([]byte(s)) } diff --git a/cmd/metronode/texture_server.go b/cmd/metronode/texture_server.go new file mode 100644 index 0000000..8f9f2aa --- /dev/null +++ b/cmd/metronode/texture_server.go @@ -0,0 +1,18 @@ +package main + +import ( + "log" + "net" + "net/http" +) + +func run_texture_server(ln net.Listener, texturesPath string) { + mux := http.NewServeMux() + mux.HandleFunc("/textures.zip", + func(w http.ResponseWriter, r *http.Request) { + log.Print("serving texture pack to ", r.RemoteAddr) + http.ServeFile(w, r, texturesPath) + }, + ) + log.Fatal(http.Serve(ln, mux)) +} diff --git a/server/player.go b/server/player.go index b7698b1..04be3fa 100644 --- a/server/player.go +++ b/server/player.go @@ -275,6 +275,14 @@ func (p *player) OnLevelData(from *level, info levelInfo, data io.ReadCloser) { Height: int16(info.Size.Y), Length: int16(info.Size.Z), }) + p.server.GetInfo(p, func(info ServerInfo) { + if info.TexturePack == "" { + return + } + p.client.SendPacket(p, &classic.SetMapEnvUrl { + TexturePackUrl: classic.PadString(info.TexturePack), + }) + }) p.client.SendPacket(p, &classic.SpawnPlayerExt { PlayerId: -1, Username: classic.PadString(p.name), diff --git a/server/server.go b/server/server.go index 407ae35..b1c64fb 100644 --- a/server/server.go +++ b/server/server.go @@ -21,11 +21,13 @@ var supportedExtensions = []string { } var requiredExtensions = []string { "ExtEntityPositions", + "EnvMapAspect.2", } type ServerInfo struct { Name string Motd string + TexturePack string } type Server struct { @@ -39,7 +41,6 @@ type Server struct { stopping bool stopped chan struct{} } - type worldState struct { LastId levelId SpawnLevel levelId @@ -185,6 +186,11 @@ func (s *Server) ExecuteCommand( }) } +func (s *Server) GetInfo(from phony.Actor, reply func(ServerInfo)) { + info := s.info + from.Act(nil, func() {reply(info)}) +} + func (s *Server) OnDisconnect(cl *client, username string, pl *player) { s.Act(cl, func() { delete(s.clients, cl) diff --git a/textures b/textures new file mode 160000 +Subproject 25d37dc5b74892886de82caf263d3040212480d |
