-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f804341
commit d55c1b7
Showing
10 changed files
with
1,092 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
|
||
} |
Oops, something went wrong.