commit
75cdac50a4
8 changed files with 349 additions and 24 deletions
|
@ -48,7 +48,14 @@ public class VideoMapPacketCodec {
|
|||
* @param posZ audio playback Z coord
|
||||
*/
|
||||
public VideoMapPacketCodec(int[][] mapIds, double posX, double posY, double posZ) {
|
||||
this(mapIds, posX, posY, posZ, 1.0f);
|
||||
this(mapIds, posX, posY, posZ, 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x])
|
||||
*/
|
||||
public VideoMapPacketCodec(int[][] mapIds) {
|
||||
this(mapIds, 0, 100, 0, 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,7 +174,7 @@ public class VideoMapPacketCodec {
|
|||
/**
|
||||
* @param url URL to an MP4 or other HTML5 supported video file
|
||||
* @param loop If the video file should loop
|
||||
* @param durationSeconds duration of the video in seconds
|
||||
* @param duration duration of the video in seconds
|
||||
* @return packet to send to players
|
||||
*/
|
||||
public byte[] beginPlayback(String url, boolean loop, float duration) {
|
||||
|
|
|
@ -28,13 +28,23 @@ public class VideoMapPacketCodecBukkit extends VideoMapPacketCodec {
|
|||
* @param posZ audio playback Z coord
|
||||
*/
|
||||
public VideoMapPacketCodecBukkit(int[][] mapIds, double posX, double posY, double posZ) {
|
||||
super(mapIds, posX, posY, posZ, 1.0f);
|
||||
super(mapIds, posX, posY, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x])
|
||||
*/
|
||||
public VideoMapPacketCodecBukkit(int[][] mapIds) {
|
||||
super(mapIds);
|
||||
}
|
||||
|
||||
public static class VideoMapPacket {
|
||||
protected final Object packet;
|
||||
protected VideoMapPacket(byte[] packet) {
|
||||
this.packet = new Packet131ItemData((short)104, (short)0, packet);
|
||||
this(packet, false);
|
||||
}
|
||||
protected VideoMapPacket(byte[] packet, boolean image) {
|
||||
this.packet = new Packet131ItemData((short)(104 + (image ? 1 : 0)), (short)0, packet);
|
||||
}
|
||||
public Object getNativePacket() {
|
||||
return packet;
|
||||
|
@ -73,6 +83,14 @@ public class VideoMapPacketCodecBukkit extends VideoMapPacketCodec {
|
|||
return new VideoMapPacket(disableVideo());
|
||||
}
|
||||
|
||||
/**
|
||||
* unloads image and resets all map object to vanilla renderer
|
||||
* @return packet to send to players
|
||||
*/
|
||||
public VideoMapPacket disableImageBukkit() {
|
||||
return new VideoMapPacket(disableVideo(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* syncs the server side video timestamp with players
|
||||
* @return packet to send to players
|
||||
|
@ -81,6 +99,14 @@ public class VideoMapPacketCodecBukkit extends VideoMapPacketCodec {
|
|||
return new VideoMapPacket(syncPlaybackWithPlayers());
|
||||
}
|
||||
|
||||
/**
|
||||
* syncs the server side image with players
|
||||
* @return packet to send to players
|
||||
*/
|
||||
public VideoMapPacket syncPlaybackWithPlayersImageBukkit() {
|
||||
return new VideoMapPacket(syncPlaybackWithPlayers(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url URL to an MP4 or other HTML5 supported video file
|
||||
* @param loop If the video file should loop
|
||||
|
@ -91,6 +117,14 @@ public class VideoMapPacketCodecBukkit extends VideoMapPacketCodec {
|
|||
return new VideoMapPacket(beginPlayback(url, loop, duration));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url URL to a PNG, JPEG, GIF, or other HTML5 supported image file
|
||||
* @return packet to send to players
|
||||
*/
|
||||
public VideoMapPacket beginPlaybackImageBukkit(String url) {
|
||||
return new VideoMapPacket(beginPlayback(url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the browser to pre-load a URL to a video to be played in the future
|
||||
* @param url the URL of the video
|
||||
|
@ -101,6 +135,16 @@ public class VideoMapPacketCodecBukkit extends VideoMapPacketCodec {
|
|||
return new VideoMapPacket(bufferVideo(url, ttl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the browser to pre-load a URL to an image to be played in the future
|
||||
* @param url the URL of the image
|
||||
* @param ttl the amount of time the image should stay loaded
|
||||
* @return packet to send to players
|
||||
*/
|
||||
public static VideoMapPacket bufferImageBukkit(String url, int ttl) {
|
||||
return new VideoMapPacket(bufferVideo(url, ttl), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param time time in seconds to seek the video to
|
||||
*/
|
||||
|
|
|
@ -675,6 +675,43 @@ public class EaglerAdapterImpl2 {
|
|||
throw new UnsupportedOperationException("Video is not supported in LWJGL runtime");
|
||||
}
|
||||
|
||||
public static final boolean isImageSupported() {
|
||||
return false;
|
||||
}
|
||||
public static final void loadImage(String src) {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final void loadImage(String src, String setJavascriptPointer) {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final void loadImage(String src, String setJavascriptPointer, String javascriptOnloadFunction) {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final void bufferImage(String src, int ttl) {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final void unloadImage() {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final boolean isImageLoaded() {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final void updateImageTexture() {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final void bindImageTexture() {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final int getImageWidth() {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final int getImageHeight() {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
public static final void setImageFrameRate(float seconds) {
|
||||
throw new UnsupportedOperationException("Image is not supported in LWJGL runtime");
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// =======================================================================================
|
||||
// =======================================================================================
|
||||
|
|
|
@ -360,4 +360,64 @@ public class ItemMap extends ItemMapBase {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void processImageMap(WorldClient theWorld, byte[] data) {
|
||||
if(!EaglerAdapter.isImageSupported()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
DataInputStream dat = new DataInputStream(new ByteArrayInputStream(data));
|
||||
int op = dat.read();
|
||||
if(op == 0) {
|
||||
int count = dat.read();
|
||||
int w = (count >> 4) & 0xF;
|
||||
int h = count & 0xF;
|
||||
for(int y = 0; y < h; ++y) {
|
||||
for(int x = 0; x < w; ++x) {
|
||||
getMapById(theWorld, dat.readUnsignedShort()).enableVideoPlayback = false;
|
||||
}
|
||||
}
|
||||
EaglerAdapter.unloadImage();
|
||||
}else if(op == 8) {
|
||||
int ttl = dat.readInt();
|
||||
String src = dat.readUTF();
|
||||
EaglerAdapter.bufferImage(src, ttl);
|
||||
}else {
|
||||
boolean fullResetPacket = (op & 2) == 2;
|
||||
boolean positionPacket = (op & 4) == 4;
|
||||
|
||||
int fps = 0;
|
||||
int len = 0;
|
||||
String url = null;
|
||||
if(fullResetPacket) {
|
||||
int count = dat.read();
|
||||
int w = (count >> 4) & 0xF;
|
||||
int h = count & 0xF;
|
||||
float wf = 1.0f / w;
|
||||
float hf = 1.0f / h;
|
||||
for(int y = 0; y < h; ++y) {
|
||||
for(int x = 0; x < w; ++x) {
|
||||
MapData mp = getMapById(theWorld, dat.readUnsignedShort());
|
||||
mp.videoX1 = x * wf;
|
||||
mp.videoY1 = y * hf;
|
||||
mp.videoX2 = mp.videoX1 + wf;
|
||||
mp.videoY2 = mp.videoY1 + hf;
|
||||
mp.enableVideoPlayback = true;
|
||||
}
|
||||
}
|
||||
fps = dat.read();
|
||||
len = dat.readInt();
|
||||
url = dat.readUTF();
|
||||
}
|
||||
|
||||
if(fullResetPacket) {
|
||||
EaglerAdapter.setImageFrameRate(fps);
|
||||
EaglerAdapter.loadImage(url);
|
||||
}
|
||||
}
|
||||
}catch(IOException e) {
|
||||
System.err.println("Failed to read image map packet! " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
|
|
@ -30,7 +30,9 @@ public class MapItemRenderer {
|
|||
float texX2 = 1.0f;
|
||||
float texY1 = 0.0f;
|
||||
float texY2 = 1.0f;
|
||||
boolean isVideoMode = EaglerAdapter.isVideoSupported() && par3MapData.enableVideoPlayback && EaglerAdapter.isVideoLoaded();
|
||||
boolean isVideoOrImageMode = EaglerAdapter.isVideoSupported() && par3MapData.enableVideoPlayback;
|
||||
boolean isVideoMode = isVideoOrImageMode && EaglerAdapter.isVideoLoaded();
|
||||
boolean isImageMode = isVideoOrImageMode && EaglerAdapter.isImageLoaded();
|
||||
if(isVideoMode) {
|
||||
EaglerAdapter.glEnable(EaglerAdapter.EAG_SWAP_RB);
|
||||
EaglerAdapter.updateVideoTexture();
|
||||
|
@ -39,6 +41,14 @@ public class MapItemRenderer {
|
|||
texY1 = par3MapData.videoY1;
|
||||
texX2 = par3MapData.videoX2;
|
||||
texY2 = par3MapData.videoY2;
|
||||
}else if(isImageMode) {
|
||||
EaglerAdapter.glEnable(EaglerAdapter.EAG_SWAP_RB);
|
||||
EaglerAdapter.updateImageTexture();
|
||||
EaglerAdapter.bindImageTexture();
|
||||
texX1 = par3MapData.videoX1;
|
||||
texY1 = par3MapData.videoY1;
|
||||
texX2 = par3MapData.videoX2;
|
||||
texY2 = par3MapData.videoY2;
|
||||
}else {
|
||||
if(par3MapData.enableAyunami) {
|
||||
System.arraycopy(par3MapData.ayunamiPixels, 0, intArray, 0, intArray.length);
|
||||
|
@ -98,11 +108,11 @@ public class MapItemRenderer {
|
|||
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
||||
par2RenderEngine.resetBoundTexture();
|
||||
|
||||
if(isVideoMode) {
|
||||
if(isVideoMode || isImageMode) {
|
||||
EaglerAdapter.glDisable(EaglerAdapter.EAG_SWAP_RB);
|
||||
}
|
||||
|
||||
if(!par3MapData.enableAyunami && !isVideoMode) {
|
||||
if(!par3MapData.enableAyunami && !(isVideoMode || isImageMode)) {
|
||||
mapicons.bindTexture();
|
||||
int var19 = 0;
|
||||
|
||||
|
|
|
@ -1017,6 +1017,8 @@ public class NetClientHandler extends NetHandler {
|
|||
ItemMap.readAyunamiMapPacket(this.mc.theWorld, par1Packet131MapData.uniqueID, par1Packet131MapData.itemData);
|
||||
} else if (par1Packet131MapData.itemID == 104) {
|
||||
ItemMap.processVideoMap(this.mc.theWorld, par1Packet131MapData.itemData);
|
||||
} else if (par1Packet131MapData.itemID == 105) {
|
||||
ItemMap.processImageMap(this.mc.theWorld, par1Packet131MapData.itemData);
|
||||
} else {
|
||||
System.err.println("Unknown itemid: " + par1Packet131MapData.itemID);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.teavm.jso.dom.html.HTMLCanvasElement;
|
|||
import org.teavm.jso.dom.html.HTMLDocument;
|
||||
import org.teavm.jso.dom.html.HTMLElement;
|
||||
import org.teavm.jso.dom.html.HTMLVideoElement;
|
||||
import org.teavm.jso.dom.html.HTMLImageElement;
|
||||
import org.teavm.jso.media.MediaError;
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.Float32Array;
|
||||
|
@ -1189,6 +1190,171 @@ public class EaglerAdapterImpl2 {
|
|||
}
|
||||
}
|
||||
|
||||
private static HTMLImageElement currentImage = null;
|
||||
private static TextureGL imageTexture = null;
|
||||
private static boolean imageIsLoaded = false;
|
||||
private static boolean imageTexIsInitialized = false;
|
||||
private static int imageFrameRate = 33;
|
||||
private static long imageFrameTimer = 0l;
|
||||
|
||||
public static final boolean isImageSupported() {
|
||||
return true;
|
||||
}
|
||||
public static final void loadImage(String src) {
|
||||
loadImage(src, null);
|
||||
}
|
||||
public static final void loadImage(String src, String setJavascriptPointer) {
|
||||
loadImage(src, setJavascriptPointer, null);
|
||||
}
|
||||
|
||||
@JSBody(params = { "ptr", "el" }, script = "window[ptr] = el;")
|
||||
private static native void setImagePointer(String ptr, HTMLImageElement el);
|
||||
@JSBody(params = { "ptr", "el" }, script = "window[ptr](el);")
|
||||
private static native void callImageLoadEvent(String ptr, HTMLImageElement el);
|
||||
|
||||
public static final void loadImage(String src, String setJavascriptPointer, final String javascriptOnloadFunction) {
|
||||
imageIsLoaded = false;
|
||||
imageTexIsInitialized = false;
|
||||
if(imageTexture == null) {
|
||||
imageTexture = _wglGenTextures();
|
||||
}
|
||||
if(currentImage != null) {
|
||||
currentImage.setSrc("");
|
||||
}
|
||||
|
||||
BufferedImageElem img = imagesBuffer.get(src);
|
||||
|
||||
if(img != null) {
|
||||
currentImage = img.imageElement;
|
||||
imagesBuffer.remove(src);
|
||||
}else {
|
||||
currentImage = (HTMLImageElement) win.getDocument().createElement("img");
|
||||
currentImage.setAttribute("crossorigin", "anonymous");
|
||||
}
|
||||
|
||||
if(setJavascriptPointer != null) {
|
||||
setImagePointer(setJavascriptPointer, currentImage);
|
||||
}
|
||||
|
||||
currentImage.addEventListener("load", new EventListener<Event>() {
|
||||
@Override
|
||||
public void handleEvent(Event evt) {
|
||||
imageIsLoaded = true;
|
||||
if(javascriptOnloadFunction != null) {
|
||||
callImageLoadEvent(javascriptOnloadFunction, currentImage);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(img == null) {
|
||||
currentImage.setSrc(src);
|
||||
}
|
||||
}
|
||||
|
||||
private static class BufferedImageElem {
|
||||
|
||||
protected final HTMLImageElement imageElement;
|
||||
protected final String url;
|
||||
protected final long requestedTime;
|
||||
protected final int ttl;
|
||||
|
||||
public BufferedImageElem(HTMLImageElement imageElement, String url, int ttl) {
|
||||
this.imageElement = imageElement;
|
||||
this.url = url;
|
||||
this.requestedTime = System.currentTimeMillis();
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final HashMap<String, BufferedImageElem> imagesBuffer = new HashMap();
|
||||
|
||||
public static final void bufferImage(String src, int ttl) {
|
||||
if(!imagesBuffer.containsKey(src)) {
|
||||
HTMLImageElement image = (HTMLImageElement) win.getDocument().createElement("img");
|
||||
image.setAttribute("crossorigin", "anonymous");
|
||||
image.setSrc(src);
|
||||
imagesBuffer.put(src, new BufferedImageElem(image, src, ttl));
|
||||
}
|
||||
}
|
||||
|
||||
public static final void unloadImage() {
|
||||
if(imageTexture != null) {
|
||||
_wglDeleteTextures(imageTexture);
|
||||
imageTexture = null;
|
||||
}
|
||||
if(currentImage != null) {
|
||||
currentImage.setSrc("");
|
||||
currentImage = null;
|
||||
}
|
||||
}
|
||||
public static final boolean isImageLoaded() {
|
||||
return imageTexture != null && currentImage != null && imageIsLoaded;
|
||||
}
|
||||
|
||||
@JSBody(
|
||||
params = {"ctx", "target", "internalformat", "format", "type", "image"},
|
||||
script = "ctx.texImage2D(target, 0, internalformat, format, type, image);"
|
||||
)
|
||||
private static native void html5ImageTexImage2D(WebGL2RenderingContext ctx, int target, int internalformat, int format, int type, HTMLImageElement image);
|
||||
|
||||
@JSBody(
|
||||
params = {"ctx", "target", "format", "type", "image"},
|
||||
script = "ctx.texSubImage2D(target, 0, 0, 0, format, type, image);"
|
||||
)
|
||||
private static native void html5ImageTexSubImage2D(WebGL2RenderingContext ctx, int target, int format, int type, HTMLImageElement image);
|
||||
|
||||
public static final void updateImageTexture() {
|
||||
long ms = System.currentTimeMillis();
|
||||
if(ms - imageFrameTimer < imageFrameRate && imageTexIsInitialized) {
|
||||
return;
|
||||
}
|
||||
imageFrameTimer = ms;
|
||||
if(currentImage != null && imageTexture != null && imageIsLoaded) {
|
||||
try {
|
||||
_wglBindTexture(_wGL_TEXTURE_2D, imageTexture);
|
||||
if(imageTexIsInitialized) {
|
||||
html5ImageTexSubImage2D(webgl, _wGL_TEXTURE_2D, _wGL_RGBA, _wGL_UNSIGNED_BYTE, currentImage);
|
||||
}else {
|
||||
html5ImageTexImage2D(webgl, _wGL_TEXTURE_2D, _wGL_RGBA, _wGL_RGBA, _wGL_UNSIGNED_BYTE, currentImage);
|
||||
_wglTexParameteri(_wGL_TEXTURE_2D, _wGL_TEXTURE_WRAP_S, _wGL_CLAMP);
|
||||
_wglTexParameteri(_wGL_TEXTURE_2D, _wGL_TEXTURE_WRAP_T, _wGL_CLAMP);
|
||||
_wglTexParameteri(_wGL_TEXTURE_2D, _wGL_TEXTURE_MIN_FILTER, _wGL_LINEAR);
|
||||
_wglTexParameteri(_wGL_TEXTURE_2D, _wGL_TEXTURE_MAG_FILTER, _wGL_LINEAR);
|
||||
imageTexIsInitialized = true;
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
// rip
|
||||
}
|
||||
}
|
||||
}
|
||||
public static final void bindImageTexture() {
|
||||
if(imageTexture != null) {
|
||||
_wglBindTexture(_wGL_TEXTURE_2D, imageTexture);
|
||||
}
|
||||
}
|
||||
public static final int getImageWidth() {
|
||||
if(currentImage != null && imageIsLoaded) {
|
||||
return currentImage.getWidth();
|
||||
}else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
public static final int getImageHeight() {
|
||||
if(currentImage != null && imageIsLoaded) {
|
||||
return currentImage.getHeight();
|
||||
}else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static final void setImageFrameRate(float fps) {
|
||||
frameRate = (int)(1000.0f / fps);
|
||||
if(frameRate < 1) {
|
||||
frameRate = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static MouseEvent currentEvent = null;
|
||||
private static KeyboardEvent currentEventK = null;
|
||||
private static boolean[] buttonStates = new boolean[8];
|
||||
|
|
Loading…
Reference in a new issue