add: more commands

This commit is contained in:
2026-02-17 09:01:41 -08:00
parent 424abfbb9e
commit ade140bb87
7 changed files with 332 additions and 44 deletions

View File

@@ -7,6 +7,7 @@ import (
"log/slog"
"os"
"os/signal"
"regexp"
"strings"
"sync"
"syscall"
@@ -20,6 +21,9 @@ import (
"tipsy.codes/charles/mc-god/v2/internal/pkg/logs"
"tipsy.codes/charles/mc-god/v2/internal/pkg/rcon"
"tipsy.codes/charles/mc-god/v2/internal/pkg/tools"
"tipsy.codes/charles/mc-god/v2/internal/pkg/tools/give"
"tipsy.codes/charles/mc-god/v2/internal/pkg/tools/say"
"tipsy.codes/charles/mc-god/v2/internal/pkg/tools/teleport"
timetool "tipsy.codes/charles/mc-god/v2/internal/pkg/tools/time"
"tipsy.codes/charles/mc-god/v2/internal/pkg/tools/weather"
"tipsy.codes/charles/mc-god/v2/internal/pkg/tools/zombie"
@@ -138,6 +142,9 @@ func main() {
weather.Get(),
zombie.Get(),
timetool.Get(),
say.Get(),
teleport.Get(),
give.Get(),
)
// Start goroutines to do the things
@@ -190,6 +197,8 @@ func main() {
[23:40:44] [Server thread/INFO]: [Not Secure] [Rcon] A name, darling? Don't keep me waiting!
[23:35:20] [Server thread/INFO]: [Rcon: Set the weather to rain & thunder]
[03:37:25] [Server thread/INFO]: [Not Secure] [Rcon] [03:37:28] [Server thread/INFO]: <BlockyMcBlockface> can i summon a zombie?
[03:52:30] [RCON Listener #1/INFO]: Thread RCON Client /127.0.0.1 started
If a player dies, mock them.
@@ -201,8 +210,10 @@ func main() {
Responses should be short; one or two sentences.
You are sending chat messages; do not annotate them with time or
make it look like a log entry.
make it look like a log entry. Do not respond to messages from yourself.
If there is nothing interesting to say, say "SKIP".
When invoking tools, make sure you match the case of the tool. "CLEAR" does not mean the same as "clear".
`,
},
},
@@ -217,13 +228,13 @@ func main() {
doneWg := sync.WaitGroup{}
doneWg.Go(handleOllama(ctx, ollamaClient, chat, rClient, tools, events))
//rconRegex := regexp.MustCompile(`^\[\d\d:\d\d:\d\d\] \[Server thread\/INFO\]: (\[Not Secure\] \[Rcon\]|\[Rcon: ) .*`)
rconRegex := regexp.MustCompile(`^\[\d\d:\d\d:\d\d\] \[Server thread\/INFO\]: (\[Not Secure\] \[Rcon\]|\[Rcon: ) .*`)
//allowedMessages := regexp.MustCompile(`^\[\d\d:\d\d:\d\d\] \[Server thread/INFO\]: (<.*>|.* has lost connection|.*left the game|.*joined the game)`)
for line := range tailer.NextLine() {
/*if rconRegex.Match([]byte(line)) {
slog.Info("Skipping line; RCON")
continue
}*/
if rconRegex.Match([]byte(line)) {
slog.Info("Skipping line; RCON")
continue
}
//if allowedMessages.Match([]byte(line)) {
slog.Info("mc log", "msg", line)
chat.AddLog(line)
@@ -237,8 +248,19 @@ func main() {
func handleOllama(ctx context.Context, client *api.Client, chat *chatContext, rClient *rcon.Client, tools tools.Tools, events chan bool) func() {
slog.Info("got chat request", "object", fmt.Sprintf("%+v", chat.chatRequest))
return func() {
// Skip past old messages
for done := false; !done; {
select {
case <-time.Tick(time.Millisecond * 50):
done = true
case <-events:
case <-ctx.Done():
return
}
}
var chatResponse api.ChatResponse
for {
<-events
chat.mu.Lock()
slog.Info("Chatting...")
// slog.Info("sending chat request", "object", fmt.Sprintf("%#v", chat.chatRequest))
@@ -260,30 +282,26 @@ func handleOllama(ctx context.Context, client *api.Client, chat *chatContext, rC
continue
}
}
if len(chatResponse.Message.ToolCalls) == 0 {
if strings.TrimSpace(chatResponse.Message.Content) == "SKIP" {
slog.Info("nothing to do; napping")
} else {
msg := chatResponse.Message.Content
msg = strings.ReplaceAll(msg, "\n", " ")
if err := rClient.Say(msg); err != nil {
slog.Error("error talking", "error", err)
if strings.TrimSpace(chatResponse.Message.Content) == "SKIP" {
slog.Info("nothing to do; napping")
} else if len(chatResponse.Message.Content) > 0 {
msg := chatResponse.Message.Content
msg = strings.ReplaceAll(msg, "\n", " ")
if err := rClient.Say(msg); err != nil {
slog.Error("error talking", "error", err)
}
var done bool
for !done {
select {
case <-events:
case <-time.Tick(time.Millisecond * 50):
done = true
case <-ctx.Done():
return
}
}
select {
case <-events:
var done bool
for !done {
select {
case <-events:
continue
case <-time.Tick(time.Millisecond * 50):
done = true
}
}
case <-ctx.Done():
return
}
// Send an event to trigger us to pass, if needed
events <- true
continue
}
}