fix: multiple bugfixes

- Fix data race: use atomic.Bool for running in server.go
- Fix busy loop in timer.go: use time.After when idle
- Fix division by zero in print_replay
- Fix silently swallowed errors in proto_generator
- Fix suppressed error in native_encoder
- Delete unused registry_data_hunter
This commit is contained in:
OpenCode
2026-08-05 14:50:10 +02:00
parent 0ed96837bd
commit 4b278b7ee3
7 changed files with 30 additions and 169 deletions
-2
View File
@@ -21,7 +21,6 @@ import (
"github.com/admin-else/strom/cmd/strom/print_replay" "github.com/admin-else/strom/cmd/strom/print_replay"
// "github.com/admin-else/strom/cmd/strom/raw_capture" // removed: use tcpflow instead for raw TCP capture // "github.com/admin-else/strom/cmd/strom/raw_capture" // removed: use tcpflow instead for raw TCP capture
"github.com/admin-else/strom/cmd/strom/raw_to_tmcpr" "github.com/admin-else/strom/cmd/strom/raw_to_tmcpr"
"github.com/admin-else/strom/cmd/strom/registry_data_hunter"
"github.com/admin-else/strom/cmd/strom/serve_tmcpr" "github.com/admin-else/strom/cmd/strom/serve_tmcpr"
"github.com/admin-else/strom/cmd/strom/serve_world" "github.com/admin-else/strom/cmd/strom/serve_world"
"github.com/admin-else/strom/cmd/strom/status" "github.com/admin-else/strom/cmd/strom/status"
@@ -64,7 +63,6 @@ var subcommands = map[string]func(args []string) error{
"print-replay": print_replay.Run, "print-replay": print_replay.Run,
// "raw-capture": raw_capture.Run, // removed: use tcpflow instead for raw TCP capture, then raw-to-tmcpr // "raw-capture": raw_capture.Run, // removed: use tcpflow instead for raw TCP capture, then raw-to-tmcpr
"raw-to-tmcpr": raw_to_tmcpr.Run, "raw-to-tmcpr": raw_to_tmcpr.Run,
"registry-data-hunter": registry_data_hunter.Run,
"serve-world": serve_world.Run, "serve-world": serve_world.Run,
"mca-to-tmcpr": mca_to_tmcpr.Run, "mca-to-tmcpr": mca_to_tmcpr.Run,
"serve-tmcpr": serve_tmcpr.Run, "serve-tmcpr": serve_tmcpr.Run,
+4
View File
@@ -212,6 +212,10 @@ func Run(args []string) (err error) {
} }
totalPackets++ totalPackets++
} }
if totalPackets > 0 {
fmt.Printf("Total packets: %d, failed packets: %d, %%failed: %.2f%%\n", totalPackets, failedPackets, float64(failedPackets)/float64(totalPackets)*100) fmt.Printf("Total packets: %d, failed packets: %d, %%failed: %.2f%%\n", totalPackets, failedPackets, float64(failedPackets)/float64(totalPackets)*100)
} else {
fmt.Printf("Total packets: %d, failed packets: %d\n", totalPackets, failedPackets)
}
return return
} }
-152
View File
@@ -1,152 +0,0 @@
package registry_data_hunter
import (
"encoding/json"
"errors"
"log/slog"
"os"
"github.com/admin-else/strom/mc/api"
"github.com/admin-else/strom/mc/client"
"github.com/admin-else/strom/mc/data"
"github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/nbt"
"github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"github.com/admin-else/strom/mc/server"
"github.com/admin-else/strom/mc/text"
)
func wontFail[T any](v T, err error) T {
if err != nil {
panic(err)
}
return v
}
var (
Version = "1.21.11"
SaveAs = "data/registry/" + Version + ".nbt"
CompatibleProtocolVersion = wontFail(data.LookUpVersionByName(Version)).Version
FinishedConfigErr = errors.New("finished configuration")
)
var Status = wontFail(json.Marshal(server.StatusResponse{
Version: server.StatusResponseVersion{
Name: nil,
Protocol: CompatibleProtocolVersion,
},
Description: text.Pretty("Registry data hunter"),
}))
type Proxy struct {
Client, Servee *proto.Conn
Data *nbt.Tag
}
func (p *Proxy) OnAnything(e event.Anything) (err error) {
packet, ok := e.Val.(proto_base.EncodeDecodeAble)
if !ok {
return
}
packetInfo, ok := proto.LookupPacketInfoByType(packet)
if !ok {
return
}
switch packetInfo.Direction {
case proto_base.ToServer:
err = p.Client.Send(packet)
case proto_base.ToClient:
err = p.Servee.Send(packet)
}
return
}
func (p *Proxy) OnFinishConfiguration(_ *v1_21_8.ConfigurationToClientPacketFinishConfiguration) (err error) {
err = FinishedConfigErr
return
}
func (p *Proxy) OnSelectKnownPacks(data *v1_21_8.ConfigurationToClientPacketCommonSelectKnownPacks) (err error) {
var entries []any
for _, entry := range data.Packs {
e := map[string]any{"Namespace": entry.Namespace, "Id": entry.Id, "Version": entry.Version}
entries = append(entries, e)
}
p.Data.Value.(map[string]any)["KnownPacks"] = entries
return
}
func (p *Proxy) OnData(data *v1_21_8.ConfigurationToClientPacketRegistryData) (err error) {
d := p.Data.Value.(map[string]any)["Registries"].([]any)
var entries []any
for _, entry := range data.Entries {
if entry.Value != nil {
entries = append(entries, map[string]any{"TagType": entry.Key, "Value": entry.Value.Value})
} else {
entries = append(entries, map[string]any{"TagType": entry.Key})
}
}
d = append(d, map[string]any{"Id": data.Id, "Entries": entries})
p.Data.Value.(map[string]any)["Registries"] = d
return
}
func (p *Proxy) OnTags(data *v1_21_8.ConfigurationToClientPacketTags) (err error) {
var tags []any
for _, tag := range data.Tags {
var entries []any
for _, entry := range tag.Tags.Val {
entries = append(entries, map[string]any{"TagName": entry.TagName, "Entries": entry.Entries})
}
tags = append(tags, map[string]any{"TagType": tag.TagType, "Entries": entries})
}
p.Data.Value.(map[string]any)["Tags"] = tags
return
}
func handleClient(c *proto.Conn) (err error) {
acc := api.NewOfflineAccount("RegistryHunter")
_, err = server.ServeLogin(c, server.WithOtherAccount(acc), server.WithCompatibleVersions(CompatibleProtocolVersion), server.WithRawStatus(Status))
if err != nil {
return
}
sockPuppet, err := client.Login(":25565", acc)
if err != nil {
return
}
defer sockPuppet.Close()
errChan := make(chan error)
p := &Proxy{Client: sockPuppet, Servee: c}
p.Data.Value = map[string]any{"Registries": []any{}}
p.Client.RegisterCritical(p.OnAnything)
p.Servee.RegisterCritical(p.OnAnything)
p.Client.RegisterCriticalUntilLatest(p.OnData)
p.Client.RegisterCriticalUntilLatest(p.OnTags)
p.Client.RegisterCriticalUntilLatest(p.OnSelectKnownPacks)
p.Client.RegisterCriticalUntilLatest(p.OnFinishConfiguration)
go func() {
errChan <- p.Client.StartConn()
}()
go func() {
errChan <- p.Servee.StartConn()
}()
err = <-errChan
f, err := os.Create(SaveAs)
if err != nil {
return
}
defer f.Close()
err = nbt.WriteUnstructuredFile(f, p.Data)
slog.Info("saved", "file", SaveAs)
return
}
func Run(args []string) error {
slog.SetLogLoggerLevel(slog.LevelDebug)
return server.StartServerWithOnConn(":25566", handleClient)
}
+7 -6
View File
@@ -23,7 +23,7 @@ type Timer struct {
Interval []IntervalTask Interval []IntervalTask
} }
func (t *Timer) Trigger(ch chan any) { func (t *Timer) Trigger(ch chan any) (didWork bool) {
triggerAt := time.Time{} triggerAt := time.Time{}
found := false found := false
iOnce, iInterval := -1, -1 iOnce, iInterval := -1, -1
@@ -46,7 +46,7 @@ func (t *Timer) Trigger(ch chan any) {
} }
if !found { if !found {
return return false
} }
now := time.Now() now := time.Now()
sleepFor := triggerAt.Sub(now) sleepFor := triggerAt.Sub(now)
@@ -55,12 +55,12 @@ func (t *Timer) Trigger(ch chan any) {
if iOnce >= 0 { if iOnce >= 0 {
ch <- CallFunc{F: reflect.ValueOf(t.Once[iOnce].F), Args: []reflect.Value{}} ch <- CallFunc{F: reflect.ValueOf(t.Once[iOnce].F), Args: []reflect.Value{}}
t.Once = slices.Delete(t.Once, iOnce, iOnce+1) t.Once = slices.Delete(t.Once, iOnce, iOnce+1)
return return true
} }
if iInterval >= 0 { if iInterval >= 0 {
t.Interval[iInterval].LastTrigger = triggerAt t.Interval[iInterval].LastTrigger = triggerAt
ch <- CallFunc{F: reflect.ValueOf(t.Interval[iInterval].F), Args: []reflect.Value{}} ch <- CallFunc{F: reflect.ValueOf(t.Interval[iInterval].F), Args: []reflect.Value{}}
return return true
} }
panic("unreachable") panic("unreachable")
} }
@@ -83,11 +83,12 @@ func (t *Timer) MakeEventSource(ctx context.Context) (chSending <-chan any) {
ch := make(chan any) ch := make(chan any)
go func() { go func() {
for { for {
if !t.Trigger(ch) {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return return
default: case <-time.After(100 * time.Millisecond):
t.Trigger(ch) }
} }
} }
}() }()
+9 -2
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"go/ast" "go/ast"
"os" "os"
"strconv" "strconv"
@@ -38,8 +39,14 @@ func GeneratePacketInfoFile(versions []string, packetInfos []PacketInfo) (err er
typeExpr = Selector(vUnderscore, typeName) typeExpr = Selector(vUnderscore, typeName)
} }
packetId, _ := strconv.ParseInt(p.PacketId, 0, 32) packetId, err := strconv.ParseInt(p.PacketId, 0, 32)
protocolVersion, _ := strconv.Atoi(p.ProtocolVersion) if err != nil {
panic(fmt.Errorf("failed to parse packet ID %q: %w", p.PacketId, err))
}
protocolVersion, err := strconv.Atoi(p.ProtocolVersion)
if err != nil {
panic(fmt.Errorf("failed to parse protocol version %q: %w", p.ProtocolVersion, err))
}
packetInfoExprs = append(packetInfoExprs, CompLit(nil, []ast.Expr{ packetInfoExprs = append(packetInfoExprs, CompLit(nil, []ast.Expr{
KeyValueExpr(Ident("Type"), AddrOf(CompLit(typeExpr, nil))), KeyValueExpr(Ident("Type"), AddrOf(CompLit(typeExpr, nil))),
+1
View File
@@ -87,6 +87,7 @@ func ArrayEncoder(g *Generator, varToSet ast.Expr, dataRaw any, name string) (s
} }
s2, err := g.VisitEncoder(Index(varToSet, Ident(iName)), data.Type, name+"Inner") s2, err := g.VisitEncoder(Index(varToSet, Ident(iName)), data.Type, name+"Inner")
if err != nil { if err != nil {
return
} }
s2 = Stmts(ForRange(Ident(iName), Call(Ident("len"), varToSet), NewBlock(s2))) s2 = Stmts(ForRange(Ident(iName), Call(Ident("len"), varToSet), NewBlock(s2)))
s = append(s1, s2...) s = append(s1, s2...)
+5 -3
View File
@@ -3,6 +3,7 @@ package server
import ( import (
"errors" "errors"
"net" "net"
"sync/atomic"
"github.com/admin-else/strom/mc/proto" "github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base" "github.com/admin-else/strom/mc/proto_base"
@@ -68,8 +69,9 @@ func StartServerWithOnConn(listenAddr string, onConn func(c *proto.Conn) (err er
return return
} }
defer l.Close() defer l.Close()
running := true running := atomic.Bool{}
for running { running.Store(true)
for running.Load() {
var cNet net.Conn var cNet net.Conn
cNet, err = l.Accept() cNet, err = l.Accept()
if err != nil { if err != nil {
@@ -80,7 +82,7 @@ func StartServerWithOnConn(listenAddr string, onConn func(c *proto.Conn) (err er
defer c.Close() defer c.Close()
connErr := onConn(c) connErr := onConn(c)
if errors.Is(connErr, ShutDownServerErr) { if errors.Is(connErr, ShutDownServerErr) {
running = false running.Store(false)
} }
c.Log.Error("closing connection", "err", connErr) c.Log.Error("closing connection", "err", connErr)
if connErr != nil { if connErr != nil {