This commit is contained in:
adman
2025-12-19 17:26:58 +01:00
parent cb38382a07
commit d7df6b25ef
20 changed files with 401 additions and 167 deletions
+67
View File
@@ -0,0 +1,67 @@
package server
import (
"log"
"net"
"github.com/admin-else/strom/event"
"github.com/admin-else/strom/proto"
"github.com/admin-else/strom/proto_base"
)
func Servee(c net.Conn) (ret *proto.Conn) {
ret = &proto.Conn{}
ret.Version = "1.21.8"
ret.State = proto_base.Handshaking
ret.CompressionThreshold = -1
ret.Actor = proto_base.Server
ret.Conn = c
ret.R = c
ret.W = c
return
}
func ServeClient(cNet net.Conn, factory func(c *proto.Conn) (h event.HandlerInst, err error)) (err error) {
c := Servee(cNet)
h, err := factory(c)
if err != nil {
return
}
err = c.Start(h)
return
}
func StartServerWithFactory(listenAddr string, factory func(c *proto.Conn) (h event.HandlerInst, err error)) (err error) {
l, err := net.Listen("tcp", listenAddr)
if err != nil {
return
}
var cNet net.Conn
for {
cNet, err = l.Accept()
if err != nil {
return
}
go ServeClient(cNet, factory)
}
}
func StartServerWithOnConn(listenAddr string, onConn func(c *proto.Conn) (err error)) (err error) {
l, err := net.Listen("tcp", listenAddr)
if err != nil {
return
}
var cNet net.Conn
for {
cNet, err = l.Accept()
if err != nil {
return
}
go func() {
connErr := onConn(Servee(cNet))
if connErr != nil {
log.Println(connErr)
}
}()
}
}
+107
View File
@@ -0,0 +1,107 @@
package server_modules
import (
"fmt"
"github.com/admin-else/strom/api"
"github.com/admin-else/strom/event"
"github.com/admin-else/strom/proto"
"github.com/admin-else/strom/proto_base"
"github.com/admin-else/strom/proto_generated/v1_21_8"
"github.com/google/uuid"
)
var UnexpectedStatusRequest = UnexpectedNextStateError{proto_base.Status}
type NameAndUUID struct {
Name string
UUID uuid.UUID
}
type UnexpectedNextStateError struct {
NextState proto_base.State
}
func (u UnexpectedNextStateError) Error() string {
return fmt.Sprintf("unexpected next state: %v", u.NextState)
}
type LoginServer struct {
*proto.Conn
//OnlineMode bool TODO: implement this
Requested NameAndUUID
Given *NameAndUUID
CompressionThreshold int32
}
func (l *LoginServer) OnHandshake(packet v1_21_8.HandshakingToServerPacketSetProtocol) (err error) {
l.State = proto_base.State(packet.NextState)
if packet.NextState != proto_base.VarInt(proto_base.Login) {
err = UnexpectedNextStateError{proto_base.State(packet.NextState)}
return
}
return
}
func (l *LoginServer) SetCompressionThreshold(threshold int32) (err error) {
err = l.Send(v1_21_8.LoginToClientPacketCompress{Threshold: proto_base.VarInt(threshold)})
if err != nil {
return
}
l.CompressionThreshold = threshold
return
}
func (l *LoginServer) OnLoginStart(packet v1_21_8.LoginToServerPacketLoginStart) (err error) {
l.Requested = NameAndUUID{packet.Username, packet.PlayerUUID}
//err = l.SetCompressionThreshold(l.CompressionThreshold)
//if err != nil {
// return
//}
if l.Given == nil {
l.Given = &l.Requested
}
err = l.Send(v1_21_8.LoginToClientPacketSuccess{
Uuid: l.Given.UUID,
Username: l.Given.Name,
Properties: nil,
})
return
}
func (l *LoginServer) OnLoginAcknowledged(_ v1_21_8.LoginToServerPacketLoginAcknowledged) (err error) {
l.State = proto_base.Configuration
err = event.HandlerDone
return
}
func (l *LoginServer) Default(event any) (err error) {
err = fmt.Errorf("unexpected event during login: %#v", event)
fmt.Println(err)
return
}
func (l *LoginServer) OnStart(_ event.OnStart) (err error) {
return
}
func (l *LoginServer) OnCycle(_ event.OnLoopCycle) (err error) {
return
}
func ServeLogin(c *proto.Conn) (ret *LoginServer, err error) {
ret = &LoginServer{Conn: c}
ret.CompressionThreshold = 256
err = ret.Start(ret)
return
}
func ServeLoginWithOtherAccount(c *proto.Conn, a *api.Account) (ret *LoginServer, err error) {
ret = &LoginServer{Conn: c, Given: &NameAndUUID{
Name: a.Name,
UUID: a.Uuid,
}}
ret.CompressionThreshold = 256
err = ret.Start(ret)
return
}
+59
View File
@@ -0,0 +1,59 @@
package server_modules
import (
"encoding/json"
"github.com/admin-else/strom/proto"
"github.com/admin-else/strom/proto_generated/v1_21_8"
)
// StatusResponse here is the structure I used: https://minecraft.wiki/w/Java_Edition_protocol/Server_List_Ping#Status_Response
type StatusResponse struct {
Version struct {
Name string `json:"name"`
Protocol int `json:"protocol"`
} `json:"version"`
Players struct {
Max int `json:"max"`
Online int `json:"online"`
Sample []struct {
Name string `json:"name"`
ID string `json:"id"`
} `json:"sample"`
} `json:"players"`
Description struct {
Text string `json:"text"`
} `json:"description"`
Favicon string `json:"favicon"`
EnforcesSecureChat bool `json:"enforcesSecureChat"`
}
type StatusServer struct {
*proto.Conn
Status string
}
func (p *StatusServer) Default(_ any) (err error) {
return
}
func (p *StatusServer) OnStatusRequest(_ v1_21_8.StatusToServerPacketPingStart) (err error) {
return p.Send(v1_21_8.StatusToClientPacketServerInfo{Response: p.Status})
}
func (p *StatusServer) OnStatusPing(packet v1_21_8.StatusToServerPacketPing) (err error) {
return p.Send(v1_21_8.StatusToClientPacketPing(packet))
}
func ServeStatus(c *proto.Conn, s StatusResponse) (err error) {
status, err := json.Marshal(s)
if err != nil {
return
}
server := &StatusServer{
Conn: c,
Status: string(status),
}
err = server.Start(server)
return
}