This commit is contained in:
AkmalFairuz
2025-12-11 08:08:58 +07:00
parent 1d40d3c7e9
commit 151816f18d
8 changed files with 79 additions and 12 deletions

4
.gitignore vendored
View File

@@ -1 +1,3 @@
.idea .idea
token.tok
example-proxy

View File

@@ -7,21 +7,21 @@ import (
"sync" "sync"
"time" "time"
"encoding/json"
"fmt"
"github.com/akmalfairuz/legacy-version/legacyver" "github.com/akmalfairuz/legacy-version/legacyver"
"github.com/pelletier/go-toml" "github.com/pelletier/go-toml"
"github.com/sandertv/gophertunnel/minecraft" "github.com/sandertv/gophertunnel/minecraft"
"github.com/sandertv/gophertunnel/minecraft/auth" "github.com/sandertv/gophertunnel/minecraft/auth"
"golang.org/x/oauth2" "golang.org/x/oauth2"
"os/signal"
"syscall"
) )
// The following program implements a proxy that forwards players from one local address to a remote address. // The following program implements a proxy that forwards players from one local address to a remote address.
func main() { func main() {
config := readConfig() config := readConfig()
token, err := auth.RequestLiveToken() src := tokenSource()
if err != nil {
panic(err)
}
src := auth.RefreshTokenSource(token)
p, err := minecraft.NewForeignStatusProvider(config.Connection.RemoteAddress) p, err := minecraft.NewForeignStatusProvider(config.Connection.RemoteAddress)
if err != nil { if err != nil {
@@ -98,6 +98,12 @@ func handleConn(conn *minecraft.Conn, listener *minecraft.Listener, config confi
} }
return return
} }
fmt.Println(pk.ID())
time.Sleep(time.Millisecond * 1000)
if pk.ID() == 498 {
fmt.Println("skipping packet 498")
continue
}
if err := conn.WritePacket(pk); err != nil { if err := conn.WritePacket(pk); err != nil {
return return
} }
@@ -144,3 +150,41 @@ func readConfig() config {
} }
return c return c
} }
// tokenSource returns a token source for using with a gophertunnel client. It either reads it from the
// token.tok file if cached or requests logging in with a device code.
func tokenSource() oauth2.TokenSource {
check := func(err error) {
if err != nil {
panic(err)
}
}
token := new(oauth2.Token)
tokenData, err := os.ReadFile("token.tok")
if err == nil {
_ = json.Unmarshal(tokenData, token)
} else {
token, err = auth.RequestLiveToken()
check(err)
}
src := auth.RefreshTokenSource(token)
_, err = src.Token()
if err != nil {
// The cached refresh token expired and can no longer be used to obtain a new token. We require the
// user to log in again and use that token instead.
token, err = auth.RequestLiveToken()
check(err)
src = auth.RefreshTokenSource(token)
}
go func() {
c := make(chan os.Signal, 3)
signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
<-c
tok, _ := src.Token()
b, _ := json.Marshal(tok)
_ = os.WriteFile("token.tok", b, 0644)
os.Exit(0)
}()
return src
}

2
go.mod
View File

@@ -33,4 +33,4 @@ require (
golang.org/x/text v0.30.0 // indirect golang.org/x/text v0.30.0 // indirect
) )
replace github.com/sandertv/gophertunnel => github.com/cooldogedev/gophertunnel v0.0.0-20251210050513-6e8700778c34 replace github.com/sandertv/gophertunnel => ../../venitydf/gophertunnel

View File

@@ -21,6 +21,7 @@ var (
// must be set to true if you're using Dragonfly. // must be set to true if you're using Dragonfly.
func All(dragonflyMapping bool) []minecraft.Protocol { func All(dragonflyMapping bool) []minecraft.Protocol {
return []minecraft.Protocol{ return []minecraft.Protocol{
New859(dragonflyMapping),
New844(dragonflyMapping), New844(dragonflyMapping),
New827(dragonflyMapping), New827(dragonflyMapping),
New819(dragonflyMapping), New819(dragonflyMapping),

View File

@@ -52,7 +52,11 @@ func (pk *CommandOutput) Marshal(io protocol.IO) {
} else { } else {
v, _ := pk.DataSet.Value() v, _ := pk.DataSet.Value()
io.String(&v) io.String(&v)
pk.DataSet = protocol.Option(v) if v != "" {
pk.DataSet = protocol.Option(v)
} else {
pk.DataSet = protocol.Optional[string]{}
}
} }
} }

View File

@@ -32,9 +32,13 @@ func (pk *Interact) Marshal(io protocol.IO) {
io.Varuint64(&pk.TargetEntityRuntimeID) io.Varuint64(&pk.TargetEntityRuntimeID)
if proto.IsProtoGTE(io, proto.ID898) { if proto.IsProtoGTE(io, proto.ID898) {
protocol.OptionalFunc(io, &pk.Position, io.Vec3) protocol.OptionalFunc(io, &pk.Position, io.Vec3)
} else { } else if pk.ActionType == packet.InteractActionMouseOverEntity || pk.ActionType == packet.InteractActionLeaveVehicle {
pos, _ := pk.Position.Value() pos, _ := pk.Position.Value()
io.Vec3(&pos) io.Vec3(&pos)
pk.Position = protocol.Option(pos) if pos != (mgl32.Vec3{}) {
pk.Position = protocol.Option(pos)
} else {
pk.Position = protocol.Optional[mgl32.Vec3]{}
}
} }
} }

View File

@@ -73,6 +73,7 @@ func (pk *Text) Marshal(io protocol.IO) {
categoryType = protocol.TextCategoryMessageWithParameters categoryType = protocol.TextCategoryMessageWithParameters
} }
io.TextCategory(&categoryType) io.TextCategory(&categoryType)
io.Uint8(&pk.TextType)
} }
switch pk.TextType { switch pk.TextType {
case TextTypeChat, TextTypeWhisper, TextTypeAnnouncement: case TextTypeChat, TextTypeWhisper, TextTypeAnnouncement:
@@ -84,6 +85,11 @@ func (pk *Text) Marshal(io protocol.IO) {
io.String(&pk.Message) io.String(&pk.Message)
protocol.FuncSlice(io, &pk.Parameters, io.String) protocol.FuncSlice(io, &pk.Parameters, io.String)
} }
if proto.IsProtoGTE(io, proto.ID898) {
if len(pk.Message) == 0 {
io.InvalidValue(pk.Message, "message", "string cannot be empty")
}
}
io.String(&pk.XUID) io.String(&pk.XUID)
io.String(&pk.PlatformChatID) io.String(&pk.PlatformChatID)
if proto.IsProtoGTE(io, proto.ID685) { if proto.IsProtoGTE(io, proto.ID685) {
@@ -92,7 +98,11 @@ func (pk *Text) Marshal(io protocol.IO) {
} else { } else {
v, _ := pk.FilteredMessage.Value() v, _ := pk.FilteredMessage.Value()
io.String(&v) io.String(&v)
pk.FilteredMessage = protocol.Option(v) if v != "" {
pk.FilteredMessage = protocol.Option(v)
} else {
pk.FilteredMessage = protocol.Optional[string]{}
}
} }
} }
} }

View File

@@ -28,11 +28,13 @@ func (x *FullContainerName) Marshal(r protocol.IO) {
r.Uint8(&x.ContainerID) r.Uint8(&x.ContainerID)
if IsProtoGTE(r, ID729) { if IsProtoGTE(r, ID729) {
protocol.OptionalFunc(r, &x.DynamicContainerID, r.Uint32) protocol.OptionalFunc(r, &x.DynamicContainerID, r.Uint32)
} else if IsProtoGTE(r, 712) { } else if IsProtoGTE(r, ID712) {
dynamicContainerID, _ := x.DynamicContainerID.Value() dynamicContainerID, _ := x.DynamicContainerID.Value()
r.Uint32(&dynamicContainerID) r.Uint32(&dynamicContainerID)
if dynamicContainerID != 0 { if dynamicContainerID != 0 {
x.DynamicContainerID = protocol.Option(dynamicContainerID) x.DynamicContainerID = protocol.Option(dynamicContainerID)
} else {
x.DynamicContainerID = protocol.Optional[uint32]{}
} }
} }
} }