Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lDEVinux
GitHub Repository: lDEVinux/eaglercraft
Path: blob/main/samples/ayunami2000/VideoMapPacketCodec.java
8641 views
1
package ayunami2000;
2
3
import java.io.ByteArrayOutputStream;
4
import java.io.DataOutputStream;
5
import java.io.IOException;
6
7
public class VideoMapPacketCodec {
8
9
public final int[][] mapIds;
10
private boolean loop;
11
private String url;
12
private int duration;
13
private long timestamp;
14
private long pauseTimestamp;
15
private double posX;
16
private double posY;
17
private double posZ;
18
private float volume;
19
private int frameRate;
20
private boolean requiresFullResetPacket;
21
private boolean requiresPositionPacket;
22
private boolean isDisabled;
23
24
/**
25
* @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x])
26
* @param posX audio playback X coord
27
* @param posY audio playback Y coord
28
* @param posZ audio playback Z coord
29
* @param volume the volume of the clip
30
*/
31
public VideoMapPacketCodec(int[][] mapIds, double posX, double posY, double posZ, float volume) {
32
this.mapIds = mapIds;
33
this.url = null;
34
this.posX = posX;
35
this.posY = posY;
36
this.posZ = posZ;
37
this.volume = volume;
38
this.frameRate = 30;
39
this.requiresPositionPacket = true;
40
this.requiresFullResetPacket = true;
41
this.isDisabled = true;
42
}
43
44
/**
45
* @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x])
46
* @param posX audio playback X coord
47
* @param posY audio playback Y coord
48
* @param posZ audio playback Z coord
49
*/
50
public VideoMapPacketCodec(int[][] mapIds, double posX, double posY, double posZ) {
51
this(mapIds, posX, posY, posZ, 0.5f);
52
}
53
54
/**
55
* @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x])
56
*/
57
public VideoMapPacketCodec(int[][] mapIds) {
58
this(mapIds, 0, 100, 0, 0.5f);
59
}
60
61
/**
62
* @param posX audio playback X coord
63
* @param posY audio playback Y coord
64
* @param posZ audio playback Z coord
65
* @param volume the volume of the clip
66
* @return packet to send to players
67
*/
68
public byte[] moveAudioSource(double posX, double posY, double posZ, float volume) {
69
this.posX = posX;
70
this.posY = posY;
71
this.posZ = posZ;
72
this.volume = volume;
73
this.requiresPositionPacket = true;
74
return syncPlaybackWithPlayers();
75
}
76
77
/**
78
* unloads video and resets all map object to vanilla renderer
79
* @return packet to send to players
80
*/
81
public byte[] disableVideo() {
82
isDisabled = true;
83
return syncPlaybackWithPlayers();
84
}
85
86
/**
87
* syncs the server side video timestamp with players
88
* @return packet to send to players
89
*/
90
public byte[] syncPlaybackWithPlayers() {
91
try {
92
ByteArrayOutputStream bao = new ByteArrayOutputStream();
93
DataOutputStream str = new DataOutputStream(bao);
94
95
if(isDisabled) {
96
str.write(0);
97
int x = mapIds[0].length;
98
int y = mapIds.length;
99
str.write((x << 4) | y);
100
for(int yy = 0; yy < y; ++yy) {
101
for(int xx = 0; xx < x; ++xx) {
102
str.writeShort(mapIds[yy][xx]);
103
}
104
}
105
return bao.toByteArray();
106
}
107
108
int packetType = 1;
109
if(requiresFullResetPacket) {
110
packetType = packetType | 2;
111
}
112
if(requiresFullResetPacket || requiresPositionPacket) {
113
packetType = packetType | 4;
114
}
115
116
str.write(packetType);
117
118
if(requiresFullResetPacket) {
119
int x = mapIds[0].length;
120
int y = mapIds.length;
121
str.write((x << 4) | y);
122
for(int yy = 0; yy < y; ++yy) {
123
for(int xx = 0; xx < x; ++xx) {
124
str.writeShort(mapIds[yy][xx]);
125
}
126
}
127
str.write(frameRate);
128
str.writeInt(duration);
129
str.writeUTF(url);
130
}
131
132
if(requiresFullResetPacket || requiresPositionPacket) {
133
str.writeFloat(volume);
134
str.writeDouble(posX);
135
str.writeDouble(posY);
136
str.writeDouble(posZ);
137
}
138
139
str.writeInt(getElapsedMillis());
140
str.writeBoolean(loop);
141
str.writeBoolean(pauseTimestamp > 0l);
142
143
requiresFullResetPacket = false;
144
requiresPositionPacket = false;
145
146
return bao.toByteArray();
147
}catch(IOException e) {
148
throw new RuntimeException("serialization error", e);
149
}
150
}
151
152
/**
153
* this is dual purpose, it calculates elapsed time but also loops or pauses the video if it is finished playing
154
*/
155
private int getElapsedMillis() {
156
if(pauseTimestamp > 0l) {
157
return (int)(pauseTimestamp - timestamp);
158
}
159
int t = (int)(System.currentTimeMillis() - timestamp);
160
if(loop) {
161
while(t > duration) {
162
t -= duration;
163
timestamp += duration;
164
}
165
}else {
166
if(t > duration) {
167
timestamp = (int)(System.currentTimeMillis() - duration);
168
return duration;
169
}
170
}
171
return t;
172
}
173
174
/**
175
* @param url URL to an MP4 or other HTML5 supported video file
176
* @param loop If the video file should loop
177
* @param duration duration of the video in seconds
178
* @return packet to send to players
179
*/
180
public byte[] beginPlayback(String url, boolean loop, float duration) {
181
this.url = url;
182
this.loop = loop;
183
this.duration = (int)(duration * 1000.0f);
184
this.pauseTimestamp = 0l;
185
this.timestamp = 0l;
186
this.requiresFullResetPacket = true;
187
this.isDisabled = false;
188
return syncPlaybackWithPlayers();
189
}
190
191
/**
192
* Tells the browser to pre-load a URL to a video to be played in the future
193
* @param url the URL of the video
194
* @param ttl the amount of time the video should stay loaded
195
* @return packet to send to players
196
*/
197
public static byte[] bufferVideo(String url, int ttl) {
198
try {
199
ByteArrayOutputStream bao = new ByteArrayOutputStream();
200
DataOutputStream str = new DataOutputStream(bao);
201
str.write(8);
202
str.writeInt(ttl);
203
str.writeUTF(url);
204
return bao.toByteArray();
205
}catch(IOException e) {
206
throw new RuntimeException("serialization error", e);
207
}
208
}
209
210
/**
211
* @return the duration of the current clip
212
*/
213
public float getDuration() {
214
return duration * 0.001f;
215
}
216
217
/**
218
* @return the URL of the current clip
219
*/
220
public String getURL() {
221
return url;
222
}
223
224
/**
225
* @return the server's current timestamp
226
*/
227
public float getPlaybackTime() {
228
return getElapsedMillis() * 0.001f;
229
}
230
231
/**
232
* @param time time in seconds to seek the video to
233
*/
234
public byte[] setPlaybackTime(float time) {
235
timestamp = System.currentTimeMillis() - (int)(time * 1000.0f);
236
return syncPlaybackWithPlayers();
237
}
238
239
/**
240
* @return if playback is complete (false if loop)
241
*/
242
public boolean isPlaybackFinished() {
243
return !loop && getElapsedMillis() == duration;
244
}
245
246
/**
247
* @param loop video should loop
248
*/
249
public byte[] setLoopEnable(boolean loop) {
250
this.loop = loop;
251
return syncPlaybackWithPlayers();
252
}
253
254
/**
255
* @return if loop is enabled
256
*/
257
public boolean isLoopEnable() {
258
return loop;
259
}
260
261
/**
262
* @param pause set if video should pause
263
* @return packet to send to players
264
*/
265
public byte[] setPaused(boolean pause) {
266
getElapsedMillis();
267
if(pause && pauseTimestamp <= 0l) {
268
pauseTimestamp = System.currentTimeMillis();
269
}else if(!pause && pauseTimestamp > 0l) {
270
timestamp = System.currentTimeMillis() - (pauseTimestamp - timestamp);
271
pauseTimestamp = 0l;
272
}
273
return syncPlaybackWithPlayers();
274
}
275
276
/**
277
* @return if video is currently paused
278
*/
279
public boolean isPaused() {
280
return pauseTimestamp > 0l;
281
}
282
283
/**
284
* @return current server-side volume
285
*/
286
public float getVolume() {
287
return volume;
288
}
289
290
}
291
292