-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpacketsession.go
More file actions
64 lines (57 loc) · 2.23 KB
/
packetsession.go
File metadata and controls
64 lines (57 loc) · 2.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package noteblockplayer
import (
"reflect"
"unsafe"
"github.com/df-mc/dragonfly/server/player"
"github.com/go-gl/mathgl/mgl64"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
// PacketPlaySound sends a PlaySound packet directly to the player's session connection.
//
// This function takes a player pointer (p), the sound name (name), float32 pitch and volume,
// and a 3D position (pos, mgl64.Vec3). It first converts the position to [3]float32 as required
// by the network packet.
//
// Then, using Go reflection and pointer-unsafe tricks, it accesses the unexported player session
// field "s" and attempts to invoke the "WritePacket" method on it. If not directly available, it
// tries to extract the connection object (field "conn") and invoke "WritePacket" on that.
//
// Ultimately, this method delivers the PlaySound packet to the player, which makes the sound
// play at the specified position with the given pitch and volume from the server side.
// This bypasses higher level APIs and directly calls the underlying session, which is
// useful for custom, low-level sound triggers in plugins or game logic.
func PacketPlaySound(p *player.Player, name string, pitch, volume float32, pos mgl64.Vec3) {
mgl32Pos := [3]float32{float32(pos[0]), float32(pos[1]), float32(pos[2])}
val := reflect.ValueOf(p).Elem().FieldByName("s")
if !val.IsValid() {
return
}
sessionPtr := reflect.NewAt(val.Type(), unsafe.Pointer(val.UnsafeAddr())).Elem()
method := sessionPtr.MethodByName("WritePacket")
if method.IsValid() {
method.Call([]reflect.Value{
reflect.ValueOf(&packet.PlaySound{
SoundName: name,
Volume: volume, // float32
Pitch: pitch, // float32
Position: mgl32Pos,
}),
})
return
}
connField := sessionPtr.Elem().FieldByName("conn")
if connField.IsValid() {
conn := reflect.NewAt(connField.Type(), unsafe.Pointer(connField.UnsafeAddr())).Elem()
writeMethod := conn.MethodByName("WritePacket")
if writeMethod.IsValid() {
writeMethod.Call([]reflect.Value{
reflect.ValueOf(&packet.PlaySound{
SoundName: name,
Volume: volume, // float32
Pitch: pitch, // float32
Position: mgl32Pos,
}),
})
}
}
}