Compare commits

...

17 Commits

Author SHA1 Message Date
Nick Dumas ac675e5c43 moving these to a more intuitive spot 1 year ago
Nick Dumas 9dc627028c use correct interpolation format 1 year ago
Nick Dumas c7c774041b labelling the docker image 1 year ago
Nick Dumas 884137a986 still no stamping 1 year ago
Nick Dumas c0e4adb98f building without errors, but still no stamping 1 year ago
Nick Dumas a35a935bab registering custom sdk so I can tap into slog 1 year ago
Nick Dumas 191725f700 Now it's choking on slog 1 year ago
Nick Dumas be601acec6 first draft at stamping, broken because i'm not using workspaces 1 year ago
Nick Dumas 68824221c1 gotta figure out stamping 1 year ago
Nick Dumas 605d728f83 everyone uses the new logger 1 year ago
Nick Dumas 2447914517 updating bazel stuff 1 year ago
Nick Dumas f3898fe694 scaffolding out ecs stuff 1 year ago
Nick Dumas e3e46ae2bd cleaning up log handling with closures 1 year ago
Nick Dumas 7766253319 adding more tracing 1 year ago
Nick Dumas 9eadcedb0b fixing a subtle bug in With() 1 year ago
Nick Dumas 07e6cab5cd significant rewrite of wrapped logger
i always want traces emitted for a few reasons
- debugging. never know when something will break.
- at some point i'm gonna want to capture and replay sessions for
  testing purposes. the trace log will make that easier
1 year ago
Nick Dumas 484fef459f make this simpler 1 year ago

@ -14,6 +14,12 @@ common --lockfile_mode=off
# editor's search path.
build --symlink_prefix=dist/
###############################
# Stamping #
###############################
# Enable this with --config=release
build:release --stamp --workspace_status_command=./tools/git-desc.sh
###############################
# Output #
###############################

3
.gitignore vendored

@ -2,7 +2,6 @@ node_modules/*
package*.json
dist/*
reports/*
lexer.log
parser.log
*.log
bazel-*
*.bazel.lock

@ -1,3 +1,4 @@
load("@rules_go//go:def.bzl", "go_library")
load("@gazelle//:def.bzl", "gazelle")
gazelle(name = "gazelle")
@ -11,3 +12,14 @@ gazelle(
],
command = "update-repos",
)
go_library(
name = "gomud",
srcs = ["version.go"],
importpath = "code.ndumas.com/ndumas/gomud",
visibility = ["//visibility:public"],
x_defs = {
"code.ndumas.com/ndumas/gomud.VERSION": "{STABLE_GIT_VERSION}",
"code.ndumas.com/ndumas/gomud.BUILD": "{STABLE_GIT_COMMIT}",
},
)

@ -10,7 +10,12 @@ bazel_dep(name = "rules_pkg", version = "0.9.1")
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")
use_repo(go_deps, "com_github_therealfakemoot_go_telnet")
use_repo(go_deps, "com_github_engoengine_ecs", "com_github_threedotslabs_watermill")
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
# Download an SDK for the host OS & architecture.
go_sdk.download(version = "1.21.0")
oci = use_extension("@rules_oci//oci:extensions.bzl", "oci")
oci.pull(

@ -1,10 +1,21 @@
load("@rules_go//go:def.bzl", "go_binary", "go_library")
load("@rules_go//go:def.bzl", "go_binary", "go_cross_binary", "go_library")
go_library(
name = "echo_lib",
srcs = ["server.go"],
srcs = ["main.go"],
importpath = "code.ndumas.com/ndumas/gomud/cmd/echo",
visibility = ["//visibility:private"],
deps = [
"//:gomud",
"//engine",
"//logger",
"//telnet",
"@com_github_engoengine_ecs//:ecs",
"@com_github_threedotslabs_watermill//message",
"@com_github_threedotslabs_watermill//message/router/middleware",
"@com_github_threedotslabs_watermill//message/router/plugin",
"@com_github_threedotslabs_watermill//pubsub/gochannel",
],
)
go_binary(
@ -13,6 +24,12 @@ go_binary(
visibility = ["//visibility:public"],
)
go_cross_binary(
name = "cross_binary",
sdk_version = "1.21.0",
target = ":echo",
)
load("@rules_pkg//:pkg.bzl", "pkg_tar")
pkg_tar(
@ -22,16 +39,22 @@ pkg_tar(
load("@rules_oci//oci:defs.bzl", "oci_image", "oci_push")
filegroup(
name = "docker_labels",
srcs = ["labels.txt"],
)
oci_image(
name = "image",
base = "@distroless_base",
entrypoint = ["/echo"],
tars = [":tar"],
labels = ":docker_labels",
)
oci_push(
name = "registry",
image = ":image",
repository = "code.ndumas.com/ndumas/gomud",
remote_tags = ["latest"],
repository = "code.ndumas.com/ndumas/gomud",
)

@ -0,0 +1,10 @@
org.label-schema.name="gomud echo"
org.label-schema.description="simple echo server for testing gomud functionality"
org.label-schema.vcs-ref=$VCS_REF // this is a git commit, parameterize this too
org.label-schema.vcs-url=code.ndumas.com/ndumas/gomud
org.label-schema.license="MIT License"
org.label-schema.schema-version="" // TODO: parameterize this
name="gomud-echo"
vendor="ndumas"
description="simple echo server for testing gomud functionality"
summary="Deploy a gomud echo server"

@ -8,35 +8,64 @@ import (
"net"
"os"
"github.com/ThreeDotsLabs/watermill"
"github.com/EngoEngine/ecs"
"github.com/ThreeDotsLabs/watermill/message"
"github.com/ThreeDotsLabs/watermill/message/router/middleware"
"github.com/ThreeDotsLabs/watermill/message/router/plugin"
"github.com/ThreeDotsLabs/watermill/pubsub/gochannel"
"code.ndumas.com/ndumas/gomud"
"code.ndumas.com/ndumas/gomud/engine"
"code.ndumas.com/ndumas/gomud/logger"
"code.ndumas.com/ndumas/gomud/telnet"
)
var (
port int
verbose int
port int
verbose int
versionFlag bool
)
func main() {
flag.IntVar(&verbose, "verbose", 0, "-5:Trace, -4:Debug, 0:Info, 4:Warn, 8:Error")
flag.IntVar(&port, "port", 5555, "MUD server port")
flag.BoolVar(&versionFlag, "version", false, "print build version")
flag.Parse()
if versionFlag {
fmt.Printf("%s@%s\n", gomud.VERSION, gomud.BUILD)
return
}
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatalf("error binding to port %d\n: %s", port, err)
}
defer l.Close()
wmLogger := watermill.NewStdLogger(false, false)
wrappedSlogger := logger.NewWrappedSlogger(os.Stdout, verbose)
traceFile, err := os.OpenFile("trace.log", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
log.Fatalf("couldn't open trace log: %s\n", err)
}
traceLogConfig := logger.LogConfig{
Writer: traceFile,
Format: "json",
Level: -5,
}
stdoutLogConfig := logger.LogConfig{
Writer: os.Stdout,
Format: "text",
Level: verbose,
}
wrappedSlogger := logger.NewWrappedSlogger(
traceLogConfig,
stdoutLogConfig,
)
router, err := message.NewRouter(message.RouterConfig{}, wrappedSlogger)
router.AddPlugin(plugin.SignalsHandler)
@ -46,19 +75,31 @@ func main() {
middleware.Recoverer,
)
pubSub := gochannel.NewGoChannel(gochannel.Config{}, wmLogger)
pubSub := gochannel.NewGoChannel(gochannel.Config{}, wrappedSlogger)
ctx := context.Background()
ts := telnet.NewTELNETServer(ctx, l, pubSub, wrappedSlogger)
tp := telnet.NewTELNETParser(ctx, pubSub, wrappedSlogger)
wrappedSlogger.Info("booting up, welcome back formers", nil)
go tp.Handle()
// create the world
world := ecs.World{}
// create systems
world.AddSystem(&engine.TELNETRenderSystem{})
// load saved state
for {
conn, err := ts.Accept()
if err != nil {
log.Fatal(err)
}
// now that i have a connection, i need to pass it to
// the telnet server for parsing incoming telnet and mud
// inputs. I also need to pass it to the RenderSystem so
// game output can be emitted to the appropriate user
go ts.Handle(conn)
go ts.Handle(wrappedSlogger)(conn)
}
}

@ -0,0 +1,18 @@
load("@rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "ecs_lib",
srcs = ["main.go"],
importpath = "code.ndumas.com/ndumas/gomud/cmd/ecs",
visibility = ["//visibility:private"],
deps = [
"//engine",
"@com_github_engoengine_ecs//:ecs",
],
)
go_binary(
name = "ecs",
embed = [":ecs_lib"],
visibility = ["//visibility:public"],
)

@ -0,0 +1,33 @@
package main
import (
// "fmt"
"github.com/EngoEngine/ecs"
"code.ndumas.com/ndumas/gomud/engine"
)
func main() {
w := ecs.World{}
trs := engine.TELNETRenderSystem{}
w.AddSystem(trs)
player1 := engine.DemoEntity{
ecs.NewBasic(),
&engine.RenderComponent{
Color: true,
},
}
w.AddEntity(&player1)
// addbyinterface isn't working right, why
w.Update(.25)
w.Update(.25)
w.Update(.25)
w.Update(.25)
w.Update(.25)
}

@ -0,0 +1,21 @@
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "ecs",
srcs = ["world.go"],
importpath = "code.ndumas.com/ndumas/gomud/ecs",
visibility = ["//visibility:public"],
deps = ["@com_github_engoengine_engo//:engo"],
)
go_library(
name = "engine",
srcs = [
"components.go",
"telnetrenderer.go",
"world.go",
],
importpath = "code.ndumas.com/ndumas/gomud/engine",
visibility = ["//visibility:public"],
deps = ["@com_github_engoengine_ecs//:ecs"],
)

@ -0,0 +1,10 @@
package engine
type LocationComponent struct {
RoomID int
}
type PlayerComponent struct {
ID int
Username string
}

@ -0,0 +1,54 @@
package engine
import (
"fmt"
"net"
"github.com/EngoEngine/ecs"
)
type RenderComponent struct {
Color bool
}
func (rc *RenderComponent) GetRenderComponent() *RenderComponent {
return rc
}
type RenderComponentInterface interface {
ecs.BasicFace
GetRenderComponent() *RenderComponent
}
type DemoEntity struct {
ecs.BasicEntity
*RenderComponent
}
type TELNETRenderSystem struct {
entities map[uint64]RenderComponentInterface
conns map[uint64]net.Conn
}
func Priority() int { return 100 }
func New(w *ecs.World) {
}
func (trs *TELNETRenderSystem) AddByInterface(o ecs.Identifier) {
fmt.Println("calling AddByInterface")
v := o.(RenderComponentInterface)
trs.entities[o.ID()] = v
}
func (trs TELNETRenderSystem) Update(dt float32) {
for _, e := range trs.entities {
fmt.Println("bing bong", e)
}
}
func (trs TELNETRenderSystem) Remove(e ecs.BasicEntity) {
}

@ -0,0 +1,3 @@
package engine
import ()

@ -2,7 +2,10 @@ module code.ndumas.com/ndumas/gomud
go 1.19
require github.com/ThreeDotsLabs/watermill v1.3.3
require (
github.com/EngoEngine/ecs v1.0.5
github.com/ThreeDotsLabs/watermill v1.3.3
)
require (
github.com/cenkalti/backoff/v3 v3.2.2 // indirect

@ -1,3 +1,5 @@
github.com/EngoEngine/ecs v1.0.5 h1:S21KTClrAqC862BFR5wTkd6uEYQ0Aw/ob9RjKPt0e30=
github.com/EngoEngine/ecs v1.0.5/go.mod h1:A8AYbzKIsl+t4qafmLL3t4H6cXdfGo4CIHl7EN100iM=
github.com/ThreeDotsLabs/watermill v1.3.3 h1:ulVgkk7n/hhWmqKKJrquWJWwIDGr9LXJ8W5XmwgSDJ4=
github.com/ThreeDotsLabs/watermill v1.3.3/go.mod h1:FUH1a4BEmr5UCmCtg7CIYvEL11mdeVBDp1404+eLP+c=
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
@ -24,5 +26,8 @@ github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

@ -0,0 +1,9 @@
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "logger",
srcs = ["wrappedslogger.go"],
importpath = "code.ndumas.com/ndumas/gomud/logger",
visibility = ["//visibility:public"],
deps = ["@com_github_threedotslabs_watermill//:watermill"],
)

@ -23,42 +23,80 @@ func LogFieldsToSlogAttrs(in watermill.LogFields) []slog.Attr {
}
type WrappedSlogger struct {
*slog.Logger
loggers []*slog.Logger
}
func NewWrappedSlogger(w io.Writer, verbose int) *WrappedSlogger {
opts := &slog.HandlerOptions{
Level: slog.Level(verbose),
type LogConfig struct {
Format string
Writer io.Writer
Level int
}
func NewWrappedSlogger(configs ...LogConfig) *WrappedSlogger {
loggers := make([]*slog.Logger, 0)
for _, config := range configs {
opts := &slog.HandlerOptions{
Level: slog.Level(config.Level),
}
var handler slog.Handler
switch config.Format {
case "json":
handler = slog.NewJSONHandler(config.Writer, opts)
case "text":
handler = slog.NewTextHandler(config.Writer, opts)
}
loggers = append(loggers, slog.New(handler))
}
handler := slog.NewTextHandler(w, opts)
return &WrappedSlogger{
slog.New(handler),
loggers: loggers,
}
}
func (wl *WrappedSlogger) Error(msg string, err error, fields watermill.LogFields) {
attrs := LogFieldsToSlogAttrs(fields)
wl.LogAttrs(nil, LevelTrace, msg, attrs...)
for _, l := range wl.loggers {
l.LogAttrs(nil, slog.LevelError, msg, attrs...)
}
}
func (wl *WrappedSlogger) Info(msg string, fields watermill.LogFields) {
attrs := LogFieldsToSlogAttrs(fields)
wl.LogAttrs(nil, slog.LevelInfo, msg, attrs...)
for _, l := range wl.loggers {
l.LogAttrs(nil, slog.LevelInfo, msg, attrs...)
}
}
func (wl *WrappedSlogger) Debug(msg string, fields watermill.LogFields) {
attrs := LogFieldsToSlogAttrs(fields)
wl.LogAttrs(nil, slog.LevelDebug, msg, attrs...)
for _, l := range wl.loggers {
l.LogAttrs(nil, slog.LevelDebug, msg, attrs...)
}
}
func (wl *WrappedSlogger) Trace(msg string, fields watermill.LogFields) {
attrs := LogFieldsToSlogAttrs(fields)
wl.LogAttrs(nil, LevelTrace, msg, attrs...)
for _, l := range wl.loggers {
l.LogAttrs(nil, LevelTrace, msg, attrs...)
}
}
func (wl *WrappedSlogger) With(fields watermill.LogFields) watermill.LoggerAdapter {
attrs := LogFieldsToSlogAttrs(fields)
l := slog.Default().With(attrs)
return &WrappedSlogger{l}
loggerArgs := make([]any, len(attrs))
for idx, attr := range attrs {
loggerArgs[idx] = attr
}
newLoggers := make([]*slog.Logger, 0)
for _, l := range wl.loggers {
newLoggers = append(newLoggers, l.With(loggerArgs...))
}
return &WrappedSlogger{loggers: newLoggers}
}

@ -6,3 +6,19 @@ go_library(
importpath = "code.ndumas.com/ndumas/gomud/protocol",
visibility = ["//visibility:public"],
)
go_library(
name = "telnet",
srcs = [
"options.go",
"parser.go",
"server.go",
],
importpath = "code.ndumas.com/ndumas/gomud/telnet",
visibility = ["//visibility:public"],
deps = [
"@com_github_threedotslabs_watermill//:watermill",
"@com_github_threedotslabs_watermill//message",
"@com_github_threedotslabs_watermill//message/router/middleware",
],
)

@ -33,8 +33,12 @@ func (tp *TELNETParser) Handle() {
func NewTELNETParser(c context.Context, s message.Subscriber, wml watermill.LoggerAdapter) *TELNETParser {
return &TELNETParser{
c: c,
s: s,
logger: wml,
c: c,
s: s,
logger: wml.With(
watermill.LogFields{
"name": "TELNETParser",
},
),
}
}

@ -21,39 +21,51 @@ type TELNETServer struct {
func NewTELNETServer(c context.Context, l net.Listener, p message.Publisher, wml watermill.LoggerAdapter) *TELNETServer {
ts := TELNETServer{
c: c,
l: l,
p: p,
logger: wml,
c: c,
l: l,
p: p,
logger: wml.With(
watermill.LogFields{
"name": "TELNETServer",
},
),
}
return &ts
}
func (ts *TELNETServer) Accept() (net.Conn, error) {
return ts.l.Accept()
conn, err := ts.l.Accept()
ts.logger.Trace("receiving telnet connection", watermill.LogFields{
"remoteAddr": conn.RemoteAddr(),
},
)
return conn, err
}
func (ts *TELNETServer) Handle(conn net.Conn) {
s := bufio.NewScanner(conn)
defer conn.Close()
// i need to create an ecs Renderer that targets a iw.Writer (net.Conn)
// the renderer
correlationID := watermill.NewUUID()
ts.logger = ts.logger.With(
func (ts *TELNETServer) Handle(wml watermill.LoggerAdapter) func(conn net.Conn) {
logger := wml.With(
watermill.LogFields{
"correlation_id": correlationID},
// "correlation_id": correlationID,
},
)
return func(conn net.Conn) {
s := bufio.NewScanner(conn)
defer conn.Close()
// i need to create an ecs Renderer that targets a iw.Writer (net.Conn)
// the renderer
correlationID := watermill.NewUUID()
for s.Scan() {
t := s.Text()
m := message.NewMessage(watermill.NewUUID(), []byte(t))
middleware.SetCorrelationID(correlationID, m)
err := ts.p.Publish("telnet.raw", m)
if err != nil {
log.Fatalln("couldn't write to telnet.raw")
for s.Scan() {
t := s.Text()
m := message.NewMessage(watermill.NewUUID(), []byte(t))
middleware.SetCorrelationID(correlationID, m)
err := ts.p.Publish("telnet.raw", m)
if err != nil {
log.Fatalln("couldn't write to telnet.raw")
}
logger.Trace("received bytes over telnet", nil)
}
ts.logger.Trace("received bytes over telnet", nil)
}
}

@ -0,0 +1,6 @@
#! /bin/bash
tag=$(git describe --tags --dirty=-dev)
commit=$(git rev-parse HEAD | head -c8)
echo "STABLE_GIT_VERSION $tag"
echo "STABLE_GIT_COMMIT $commit"

@ -0,0 +1,6 @@
package gomud
const (
VERSION = ""
BUILD = ""
)
Loading…
Cancel
Save