-
Notifications
You must be signed in to change notification settings - Fork 95
/
resource_pack_queue.go
93 lines (84 loc) · 2.93 KB
/
resource_pack_queue.go
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package minecraft
import (
"bytes"
"fmt"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
"github.com/sandertv/gophertunnel/minecraft/resource"
)
// resourcePackQueue is used to aid in the handling of resource pack queueing and downloading. Only one
// resource pack is downloaded at a time.
type resourcePackQueue struct {
packs []*resource.Pack
packsToDownload map[string]*resource.Pack
currentPack *resource.Pack
currentOffset uint64
packAmount int
downloadingPacks map[string]downloadingPack
awaitingPacks map[string]*downloadingPack
}
// downloadingPack is a resource pack that is being downloaded by a client connection.
type downloadingPack struct {
buf *bytes.Buffer
chunkSize uint32
size uint64
expectedIndex uint32
newFrag chan []byte
contentKey string
}
// Request 'requests' all resource packs passed, provided they all exist in the resourcePackQueue. If not,
// an error is returned.
func (queue *resourcePackQueue) Request(packs []string) error {
queue.packsToDownload = make(map[string]*resource.Pack)
for _, packUUID := range packs {
found := false
for _, pack := range queue.packs {
// Mojang made some hack that merges the UUID with the version, so we need to combine that here
// too in order to find the proper pack.
if pack.UUID()+"_"+pack.Version() == packUUID {
queue.packsToDownload[pack.UUID()] = pack
found = true
break
}
}
if !found {
return fmt.Errorf("could not find resource pack %v", packUUID)
}
}
return nil
}
// NextPack assigns the next resource pack to the current pack and returns true if successful. If there were
// no more packs to assign, false is returned. If ok is true, a packet with data info is returned.
func (queue *resourcePackQueue) NextPack() (pk *packet.ResourcePackDataInfo, ok bool) {
for index, pack := range queue.packsToDownload {
delete(queue.packsToDownload, index)
queue.currentPack = pack
queue.currentOffset = 0
checksum := pack.Checksum()
var packType byte
switch {
case pack.HasWorldTemplate():
packType = packet.ResourcePackTypeWorldTemplate
case pack.HasTextures() && (pack.HasBehaviours() || pack.HasScripts()):
packType = packet.ResourcePackTypeAddon
case !pack.HasTextures() && (pack.HasBehaviours() || pack.HasScripts()):
packType = packet.ResourcePackTypeBehaviour
case pack.HasTextures():
packType = packet.ResourcePackTypeResources
default:
packType = packet.ResourcePackTypeSkins
}
return &packet.ResourcePackDataInfo{
UUID: pack.UUID(),
DataChunkSize: packChunkSize,
ChunkCount: uint32(pack.DataChunkCount(packChunkSize)),
Size: uint64(pack.Len()),
Hash: checksum[:],
PackType: packType,
}, true
}
return nil, false
}
// AllDownloaded checks if all resource packs in the queue are downloaded.
func (queue *resourcePackQueue) AllDownloaded() bool {
return len(queue.packsToDownload) == 0
}