Added full RGB map packets for ayunami2000

This commit is contained in:
LAX1DUDE 2022-04-15 22:38:43 -07:00
parent d115c2da03
commit 9564621e78
11 changed files with 664 additions and 63 deletions

View file

@ -0,0 +1,232 @@
package ayunami2000;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
public class MapPacketCodec {
public interface FragmentHandler {
void sendFragment(byte[] data, boolean isLastFragment);
}
public enum PixelFormat {
R5_G6_B5, R8_G8_B8
}
public final int mapId;
private Deflater deflate = null;
private PixelFormat pixelFormat = PixelFormat.R5_G6_B5;
private int[] pixels = null;
private int[] pallete = null;
private boolean palleteIsSet = false;
private boolean palleteIsDirty = false;
/**
* @param mapId the ID of the map item to write to
*/
public MapPacketCodec(int mapId) {
this.mapId = mapId;
}
/**
* @param enable enables java.util.zip deflate on packets encoded by this class
*/
public MapPacketCodec deflate(boolean enable) {
deflate(enable ? 5 : 0);
return this;
}
/**
* @param level sets or disables compression level (0-9)
*/
public MapPacketCodec deflate(int level) {
deflate = level > 0 ? new Deflater(level) : null;
return this;
}
/**
* @param pix sets if pixels should be encoded as 16 bits per pixel or 24 bits per pixel
*/
public MapPacketCodec pixelFormat(PixelFormat pix) {
pixelFormat = pix == null ? PixelFormat.R5_G6_B5 : pix;
return this;
}
/**
* @param pixels If pallete is disabled, array of 16384 integers each containing the RGB of a pixel. If
* pallete is enabled, array of 16384 integers each containing an index in the current pallete between 0 and 255
*/
public MapPacketCodec setPixels(int[] pixels) {
if(pixels != null && pixels.length != 16384) {
throw new IllegalArgumentException("Pixel array must be 16384 pixels long");
}
this.pixels = pixels;
return this;
}
/**
* @param pixels a 128x128 RGB java.awt.image.BufferedImage, this will disable the pallete
*/
public MapPacketCodec setPixels(BufferedImage pixels) {
if(pixels.getWidth() != 128 || pixels.getHeight() != 128) {
throw new IllegalArgumentException("BufferedImage must be 128x128 pixels");
}
palleteIsSet = false;
this.pallete = null;
palleteIsDirty = false;
int[] pxls = new int[16384];
pixels.getRGB(0, 0, 128, 128, pxls, 0, 128);
setPixels(pxls);
return this;
}
/**
* sets and enables the pallete, or disables it if 'pallete' is null
*
* @param pallete an array of any size between 1 and 256 containing integers each representing a single RGB color
*/
public MapPacketCodec setPallete(int[] pallete) {
boolean b = pallete != null;
if(b) {
palleteIsSet = true;
this.pallete = pallete;
palleteIsDirty = true;
}else {
if(pixels != null && this.pallete != null) {
int[] px = pixels;
pixels = new int[16384];
for(int i = 0; i < 16384; ++i) {
int j = px[i];
pixels[i] = this.pallete[j >= this.pallete.length ? 0 : j];
}
}
this.pallete = null;
palleteIsSet = false;
palleteIsDirty = false;
}
return this;
}
/**
* Disables the pallete
*/
public MapPacketCodec clearPallete() {
setPallete(null);
return this;
}
/*
* Operations:
*
* - 0: disable engine
* - 1: compressed data
*
* - 2: set pixels R8_G8_B8
* - 3: set pixels R5_G6_B5
* - 4: set pallete R8_G8_B8
* - 5: set pallete R5_G6_B5
* - 6: set pixels via pallete
* - 7: set pallete and pixels R8_G8_B8
* - 8: set pallete and pixels R5_G6_B5
*
*/
/**
* takes the current pixels array and writes it to a packet and returns it, or returns null if the current pixels array has not changed
*/
public byte[] getNextPacket() {
if(pixels == null) {
return null;
}
try {
ByteArrayOutputStream o = new ByteArrayOutputStream();
DataOutputStream s;
if(deflate != null) {
o.write(1);
s = new DataOutputStream(new DeflaterOutputStream(o, deflate));
}else {
s = new DataOutputStream(o);
}
if(!palleteIsSet || pallete == null) {
palleteIsSet = false;
if(pixelFormat == PixelFormat.R5_G6_B5) {
s.write(3);
for(int i = 0; i < 16384; ++i) {
int j = pixels[i];
int r = (j >> 19) & 0x1F;
int g = (j >> 10) & 0x3F;
int b = (j >> 3) & 0x1F;
s.writeShort((r << 11) | (g << 5) | b);
}
}else if(pixelFormat == PixelFormat.R8_G8_B8) {
s.write(2);
for(int i = 0; i < 16384; ++i) {
int j = pixels[i];
s.write((j >> 16) & 0xFF);
s.write((j >> 8) & 0xFF);
s.write(j & 0xFF);
}
}else {
return null; // ?
}
}else {
if(palleteIsDirty) {
if(pixelFormat == PixelFormat.R5_G6_B5) {
s.write(8);
s.write(pallete.length);
for(int i = 0; i < pallete.length; ++i) {
int j = pallete[i];
int r = (j >> 19) & 0x1F;
int g = (j >> 10) & 0x3F;
int b = (j >> 3) & 0x1F;
s.writeShort((r << 11) | (g << 5) | b);
}
}else if(pixelFormat == PixelFormat.R8_G8_B8) {
s.write(7);
s.write(pallete.length);
for(int i = 0; i < pallete.length; ++i) {
int j = pallete[i];
s.write((j >> 16) & 0xFF);
s.write((j >> 8) & 0xFF);
s.write(j & 0xFF);
}
}else {
return null; // ?
}
palleteIsDirty = false;
}else {
s.write(6);
}
for(int i = 0; i < 16384; ++i) {
s.write(pixels[i]);
}
}
pixels = null;
s.close();
return o.toByteArray();
}catch(IOException e) {
throw new RuntimeException("Failed to write ayunami map packet");
}
}
public byte[] getDisablePacket() {
try {
palleteIsSet = false;
palleteIsDirty = false;
pallete = null;
pixels = null;
ByteArrayOutputStream o = new ByteArrayOutputStream();
DataOutputStream s = new DataOutputStream(o);
s.writeShort(mapId);
s.write(0);
return o.toByteArray();
}catch(IOException e) {
throw new RuntimeException("Failed to write ayunami map packet");
}
}
}

View file

@ -0,0 +1,76 @@
package ayunami2000;
import java.util.List;
import org.bukkit.craftbukkit.v1_5_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import net.minecraft.server.v1_5_R3.Packet;
import net.minecraft.server.v1_5_R3.Packet131ItemData;
public class MapPacketCodecBukkit extends MapPacketCodec {
public MapPacketCodecBukkit(int mapId) {
super(mapId);
}
public Object getNextBukkitPacket() {
byte[] pkt = getNextPacket();
if(pkt == null) {
return null;
}
return new Packet131ItemData((short)103, (short)mapId, pkt);
}
public Object getDisableBukkitPacket() {
byte[] pkt = getDisablePacket();
if(pkt == null) {
return null;
}
return new Packet131ItemData((short)103, (short)mapId, pkt);
}
public void sendNextPacketToPlayer(Player p) {
nativeSendPacketToPlayer(p, getNextBukkitPacket());
}
public void sendDisablePacketToPlayer(Player p) {
nativeSendPacketToPlayer(p, getDisableBukkitPacket());
}
public void sendNextPacketToPlayers(Player... p) {
Object pkt = getNextBukkitPacket();
for(Player pl : p) {
nativeSendPacketToPlayer(pl, pkt);
}
}
public void sendDisablePacketToPlayers(Player... p) {
Object pkt = getDisableBukkitPacket();
for(Player pl : p) {
nativeSendPacketToPlayer(pl, pkt);
}
}
public void sendNextPacketToPlayers(List<Player> p) {
Object pkt = getNextBukkitPacket();
for(Player pl : p) {
nativeSendPacketToPlayer(pl, pkt);
}
}
public void sendDisablePacketToPlayers(List<Player> p) {
Object pkt = getDisableBukkitPacket();
for(Player pl : p) {
nativeSendPacketToPlayer(pl, pkt);
}
}
public static void nativeSendPacketToPlayer(Player player, Object obj) {
if(obj == null) {
return;
}
((CraftPlayer)player).getHandle().playerConnection.sendPacket((Packet)obj);
}
}

11
samples/plugin.yml Normal file
View file

@ -0,0 +1,11 @@
name: EaglerSamplesPlugin
main: plugin.EaglerSamplesPlugin
version: 1.0
author: lax1dude
description: eagler
depend: []
commands:
samplemap:
description: test ayunami map system
usage: /samplemap <get|disable|set> [mapid] [image file] [16bpp|24bpp] [compress]
permission: eaglersamples.samplemap

View file

@ -0,0 +1,116 @@
package plugin;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import ayunami2000.MapPacketCodec.PixelFormat;
import ayunami2000.MapPacketCodecBukkit;
public class CommandSampleMap implements CommandExecutor {
public final EaglerSamplesPlugin plugin;
public CommandSampleMap(EaglerSamplesPlugin plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender arg0, Command arg01, String arg1, String[] arg2) {
if(!(arg0 instanceof Player)) {
arg0.sendMessage(ChatColor.RED + "Internal Error: " + ChatColor.WHITE + "CommmandSender must be a Player");
return false;
}
arg0.sendMessage(ChatColor.YELLOW + "Note: test packets are only sent to the player running this command");
Player p = (Player)arg0;
try {
int mapId = -1;
if(arg2.length >= 2) {
mapId = Integer.parseInt(arg2[1]);
}else {
ItemStack i = p.getInventory().getItemInHand();
if(i.getType() == Material.MAP) {
mapId = (int)i.getDurability() & 0xFFFF;
}
}
if(mapId != -1) {
if(arg2.length == 1) {
if(arg2[0].equalsIgnoreCase("get")) {
arg0.sendMessage(ChatColor.GREEN + "Current map ID: " + ChatColor.WHITE + mapId);
return true;
}else if(arg2[0].equalsIgnoreCase("disable")) {
MapPacketCodecBukkit pkt = new MapPacketCodecBukkit(mapId);
pkt.sendDisablePacketToPlayer(p);
arg0.sendMessage(ChatColor.GREEN + "Reset map: " + ChatColor.WHITE + mapId);
return true;
}else if(arg2[0].equalsIgnoreCase("set")) {
arg0.sendMessage(ChatColor.RED + "Use: " + ChatColor.WHITE + "/samplemap set <file> [compress]");
return true;
}else {
MapPacketCodecBukkit pkt = new MapPacketCodecBukkit(mapId);
BufferedImage img = ImageIO.read(new File(arg2[0]));
pkt.setPixels(img);
pkt.sendNextPacketToPlayer(p);
arg0.sendMessage(ChatColor.GREEN + "Wrote image " + ChatColor.WHITE + arg2[0] + ChatColor.GREEN + " to map " + ChatColor.WHITE + mapId);
return true;
}
}else if(arg2.length == 2) {
int j = Integer.parseInt(arg2[1]);
if(arg2[0].equalsIgnoreCase("disable")) {
MapPacketCodecBukkit pkt = new MapPacketCodecBukkit(j);
pkt.sendDisablePacketToPlayer(p);
arg0.sendMessage(ChatColor.GREEN + "Reset map: " + ChatColor.WHITE + j);
return true;
}
}else if(arg2.length >= 3) {
int j = Integer.parseInt(arg2[1]);
MapPacketCodecBukkit pkt = new MapPacketCodecBukkit(j);
BufferedImage img = ImageIO.read(new File(arg2[2]));
if(arg2.length == 4 || arg2.length == 5) {
if(arg2[3].equalsIgnoreCase("16bpp")) {
pkt.pixelFormat(PixelFormat.R5_G6_B5);
if(arg2.length == 5) {
if(arg2[4].equalsIgnoreCase("true")) {
pkt.deflate(true);
}else {
pkt.deflate(Integer.parseInt(arg2[4]));
}
}
}else if(arg2[3].equalsIgnoreCase("24bpp")) {
pkt.pixelFormat(PixelFormat.R8_G8_B8);
if(arg2.length == 5) {
if(arg2[4].equalsIgnoreCase("true")) {
pkt.deflate(true);
}else {
pkt.deflate(Integer.parseInt(arg2[4]));
}
}
}else if(arg2[3].equalsIgnoreCase("true")) {
pkt.deflate(true);
}else {
pkt.deflate(Integer.parseInt(arg2[3]));
}
}
pkt.setPixels(img);
pkt.sendNextPacketToPlayer(p);
arg0.sendMessage(ChatColor.GREEN + "Wrote image " + ChatColor.WHITE + arg2[2] + ChatColor.GREEN + " to map " + ChatColor.WHITE + mapId);
return true;
}
}
}catch(Throwable t) {
arg0.sendMessage(ChatColor.RED + "Internal Error: " + ChatColor.WHITE + t.toString());
t.printStackTrace();
}
return false;
}
}

View file

@ -0,0 +1,14 @@
package plugin;
import org.bukkit.plugin.java.JavaPlugin;
public class EaglerSamplesPlugin extends JavaPlugin {
public void onEnable() {
getCommand("samplemap").setExecutor(new CommandSampleMap(this));
}
public void onDisable() {
}
}

1
samples/readme.txt Normal file
View file

@ -0,0 +1 @@
These are sample source files to assist the process of integrating Eaglercraft into other projects, or to assist the process of integrating other projects into Eaglercraft

View file

@ -908,7 +908,7 @@ public class EaglerAdapterImpl2 {
}else {
rateLimitStatus = RateLimit.FAILED;
}
}else if(!socketIsAlive) {
}else if(!socketIsAlive && (blockedAddresses.contains(serverUriString) || rateLimitedAddresses.contains(serverUriString))) {
rateLimitStatus = RateLimit.LOCKED;
}
}

View file

@ -1,9 +1,9 @@
package net.minecraft.src;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
public class ItemMap extends ItemMapBase {
protected ItemMap(int par1) {
super(par1);
@ -256,4 +256,21 @@ public class ItemMap extends ItemMapBase {
}
}
}
public static void readAyunamiMapPacket(WorldClient theWorld, short mapId, byte[] data) {
try {
String var2 = "map_" + mapId;
MapData var3 = (MapData) theWorld.loadItemData(MapData.class, var2);
if (var3 == null) {
var3 = new MapData(var2);
theWorld.setItemData(var2, var3);
}
var3.readAyunamiMapPacket(new ByteArrayInputStream(data));
}catch(IOException e) {
System.err.println("Failed to read AyunamiMap packet! " + e.toString());
e.printStackTrace();
}
}
}

View file

@ -1,11 +1,17 @@
package net.minecraft.src;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.jcraft.jzlib.InflaterInputStream;
public class MapData extends WorldSavedData {
@ -240,4 +246,130 @@ public class MapData extends WorldSavedData {
return var2;
}
public boolean enableAyunami = false;
public int[] ayunamiPixels = null;
private int[] ayunamiPallete = null;
/**
* Operations:
*
* - 0: disable engine
* - 1: compressed data
*
* - 2: set pixels R8_G8_B8
* - 3: set pixels R5_G6_B5
* - 4: set pallete R8_G8_B8
* - 5: set pallete R5_G6_B5
* - 6: set pixels via pallete
* - 7: set pallete and pixels R8_G8_B8
* - 8: set pallete and pixels R5_G6_B5
*
*/
public void readAyunamiMapPacket(InputStream dat) throws IOException {
int operation = dat.read();
DataInputStream ddat;
switch(operation) {
case 0:
ayunamiDisable();
break;
case 1:
readAyunamiMapPacket(new InflaterInputStream(dat));
break;
case 2:
ayunamiSetPixels_R8_G8_B8(new DataInputStream(dat));
break;
case 3:
ayunamiSetPixels_R5_G6_B5(new DataInputStream(dat));
break;
case 4:
ayunamiSetPallete_R8_G8_B8(new DataInputStream(dat));
break;
case 5:
ayunamiSetPallete_R5_G6_B5(new DataInputStream(dat));
break;
case 6:
ayunamiSetPixelsFromPallete(new DataInputStream(dat));
break;
case 7:
ddat = new DataInputStream(dat);
ayunamiSetPallete_R8_G8_B8(ddat);
ayunamiSetPixelsFromPallete(ddat);
break;
case 8:
ddat = new DataInputStream(dat);
ayunamiSetPallete_R5_G6_B5(ddat);
ayunamiSetPixelsFromPallete(ddat);
break;
default:
throw new IOException("Unknown map packet type: " + operation);
}
}
private void ayunamiDisable() {
if(enableAyunami) {
enableAyunami = false;
ayunamiPixels = null;
ayunamiPallete = null;
}
}
private void ayunamiEnable() {
if(!enableAyunami) {
enableAyunami = true;
ayunamiPixels = new int[16384];
ayunamiPallete = new int[256];
}
}
private void ayunamiSetPixels_R8_G8_B8(DataInputStream dat) throws IOException {
ayunamiEnable();
for(int i = 0; i < ayunamiPixels.length; ++i) {
ayunamiPixels[i] = -16777216 | (dat.read() << 16) | (dat.read() << 8) | dat.read();
}
}
private void ayunamiSetPixels_R5_G6_B5(DataInputStream dat) throws IOException {
ayunamiEnable();
for(int i = 0; i < ayunamiPixels.length; ++i) {
int j = (int)dat.readShort() & 0xFFFF;
int r = ((j >> 11) & 0x1F);
int g = ((j >> 5) & 0x3F);
int b = (j & 0x1F);
ayunamiPixels[i] = -16777216 | (r << 19) | (g << 10) | (b << 3);
}
}
private void ayunamiSetPallete_R8_G8_B8(DataInputStream dat) throws IOException {
ayunamiEnable();
int len = dat.read();
ayunamiPallete = new int[len];
for(int i = 0; i < len; ++i) {
ayunamiPallete[i] = -16777216 | (dat.read() << 16) | (dat.read() << 8) | dat.read();
}
}
private void ayunamiSetPallete_R5_G6_B5(DataInputStream dat) throws IOException {
ayunamiEnable();
int len = dat.read();
ayunamiPallete = new int[len];
for(int i = 0; i < len; ++i) {
int j = (int)dat.readShort() & 0xFFFF;
int r = ((j >> 11) & 0x1F);
int g = ((j >> 5) & 0x3F);
int b = (j & 0x1F);
ayunamiPixels[i] = -16777216 | (r << 19) | (g << 10) | (b << 3);
}
}
private void ayunamiSetPixelsFromPallete(DataInputStream dat) throws IOException {
ayunamiEnable();
for(int i = 0; i < ayunamiPixels.length; ++i) {
ayunamiPixels[i] = ayunamiPallete[dat.read()];
}
}
}

View file

@ -26,6 +26,9 @@ public class MapItemRenderer {
private static final TextureLocation mapicons = new TextureLocation("/misc/mapicons.png");
public void renderMap(EntityPlayer par1EntityPlayer, RenderEngine par2RenderEngine, MapData par3MapData) {
if(par3MapData.enableAyunami) {
System.arraycopy(par3MapData.ayunamiPixels, 0, intArray, 0, intArray.length);
}else {
for (int var4 = 0; var4 < 16384; ++var4) {
byte var5 = par3MapData.colors[var4];
@ -60,6 +63,7 @@ public class MapItemRenderer {
this.intArray[var4] = -16777216 | var9 << 16 | var10 << 8 | var11;
}
}
}
par2RenderEngine.createTextureFromBytes(this.intArray, 128, 128, this.bufferedImage);
byte var15 = 0;
@ -79,6 +83,8 @@ public class MapItemRenderer {
EaglerAdapter.glEnable(EaglerAdapter.GL_ALPHA_TEST);
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
par2RenderEngine.resetBoundTexture();
if(!par3MapData.enableAyunami) {
mapicons.bindTexture();
int var19 = 0;
@ -101,10 +107,6 @@ public class MapItemRenderer {
var17.draw();
EaglerAdapter.glPopMatrix();
}
EaglerAdapter.glPushMatrix();
EaglerAdapter.glTranslatef(0.0F, 0.0F, -0.04F);
EaglerAdapter.glScalef(1.0F, 1.0F, 1.0F);
EaglerAdapter.glPopMatrix();
}
}
}

View file

@ -5,11 +5,9 @@ import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.lax1dude.eaglercraft.DefaultSkinRenderer;
import net.lax1dude.eaglercraft.EaglerAdapter;
@ -1015,8 +1013,10 @@ public class NetClientHandler extends NetHandler {
public void handleMapData(Packet131MapData par1Packet131MapData) {
if (par1Packet131MapData.itemID == Item.map.itemID) {
ItemMap.getMPMapData(par1Packet131MapData.uniqueID, this.mc.theWorld).updateMPMapData(par1Packet131MapData.itemData);
} else if (par1Packet131MapData.itemID == 103) {
ItemMap.readAyunamiMapPacket(this.mc.theWorld, par1Packet131MapData.uniqueID, par1Packet131MapData.itemData);
} else {
System.err.println("Unknown itemid: " + par1Packet131MapData.uniqueID);
System.err.println("Unknown itemid: " + par1Packet131MapData.itemID);
}
}