mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-24 05:03:34 -04:00
Implement FastMap CPE extension
This commit is contained in:
parent
d140333461
commit
3e2f072666
@ -53,8 +53,8 @@ namespace MCGalaxy.Commands.Fun {
|
||||
public override void Help(Player p) {
|
||||
Player.Message(p, "%T/Queue zombie [name]");
|
||||
Player.Message(p, "%HNext round [name] will be infected/start zombie");
|
||||
Player.Message(p, "%T/Queue level [name]");
|
||||
Player.Message(p, "%HNext round [name] will be the level used");
|
||||
Player.Message(p, "%T/Queue level [map]");
|
||||
Player.Message(p, "%HNext round [map] will be the level used");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,8 +54,8 @@ namespace MCGalaxy.Commands.World {
|
||||
public override void Help(Player p) {
|
||||
Player.Message(p, "%T/Main");
|
||||
Player.Message(p, "%HSends you to the main level.");
|
||||
Player.Message(p, "%T/Main [level]");
|
||||
Player.Message(p, "%HSets the main level to that level.");
|
||||
Player.Message(p, "%T/Main [map]");
|
||||
Player.Message(p, "%HSets the main level to that map.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ namespace MCGalaxy.Commands.World {
|
||||
static string GetBool(bool value) { return value ? "&aON" : "&cOFF"; }
|
||||
|
||||
public override void Help(Player p) {
|
||||
Player.Message(p, "%T/Map [level] [option] <value> %H- Sets [option] on [level]");
|
||||
Player.Message(p, "%T/Map [map] [option] <value> %H- Sets [option] on that map");
|
||||
Player.Message(p, "%HPossible options: %S{0}", LevelOptions.Options.Keys.Join());
|
||||
Player.Message(p, "%HUse %T/Help map [option] %Hto see description for that option.");
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ namespace MCGalaxy.Commands.World {
|
||||
string map = args.Length == 1 ? p.level.name : Matcher.FindMaps(p, args[0]);
|
||||
if (map == null) return;
|
||||
Level lvl;
|
||||
LevelConfig cfg = LevelInfo.GetConfig(map, out lvl);
|
||||
LevelConfig cfg = LevelInfo.GetConfig(map, out lvl);
|
||||
int offset = args.Length == 1 ? 0 : 1;
|
||||
|
||||
AccessController access;
|
||||
@ -94,13 +94,13 @@ namespace MCGalaxy.Commands.World {
|
||||
}
|
||||
|
||||
protected void ShowHelp(Player p, string action, string action2) {
|
||||
Player.Message(p, "%T/{0} [level] [rank]", name);
|
||||
Player.Message(p, "%HSets the lowest rank able to {0} the given level.", action);
|
||||
Player.Message(p, "%T/{0} -max [Level] [Rank]", name);
|
||||
Player.Message(p, "%HSets the highest rank able to {0} the given level.", action);
|
||||
Player.Message(p, "%T/{0} [level] +[name]", name);
|
||||
Player.Message(p, "%T/{0} [map] [rank]", name);
|
||||
Player.Message(p, "%HSets the lowest rank able to {0} the given map.", action);
|
||||
Player.Message(p, "%T/{0} -max [map] [Rank]", name);
|
||||
Player.Message(p, "%HSets the highest rank able to {0} the given map.", action);
|
||||
Player.Message(p, "%T/{0} [map] +[name]", name);
|
||||
Player.Message(p, "%HAllows [name] to {0}, even if their rank cannot.", action2);
|
||||
Player.Message(p, "%T/{0} [level] -[name]", name);
|
||||
Player.Message(p, "%T/{0} [map] -[name]", name);
|
||||
Player.Message(p, "%HPrevents [name] from {0}ing, even if their rank can.", action2);
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ namespace MCGalaxy.Eco {
|
||||
}
|
||||
|
||||
protected internal override void OnStoreCommand(Player p) {
|
||||
Player.Message(p, "%T/Buy {0} [map name]", Name);
|
||||
Player.Message(p, "%T/Buy {0} [map]", Name);
|
||||
OutputItemInfo(p);
|
||||
Player.Message(p, "The map used for the next round of " +
|
||||
"zombie survival will be the given map.");
|
||||
|
@ -46,7 +46,13 @@ namespace MCGalaxy.Network {
|
||||
|
||||
public static byte[] Ping() { return new byte[] { Opcode.Ping }; }
|
||||
|
||||
public static byte[] LevelInitalise() { return new byte[] { Opcode.LevelInitialise }; }
|
||||
public static byte[] LevelInitalise() { return new byte[] { Opcode.LevelInitialise }; }
|
||||
public static byte[] LevelInitaliseExt(int volume) {
|
||||
byte[] buffer = new byte[5];
|
||||
buffer[0] = Opcode.LevelInitialise;
|
||||
NetUtils.WriteI32(volume, buffer, 1);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static byte[] LevelFinalise(ushort width, ushort height, ushort length) {
|
||||
byte[] buffer = new byte[7];
|
||||
@ -230,7 +236,7 @@ namespace MCGalaxy.Network {
|
||||
}
|
||||
|
||||
public static byte[] BlockPermission(BlockID raw, bool place, bool delete, bool extBlocks) {
|
||||
byte[] buffer = new byte[extBlocks ? 5 : 4];
|
||||
byte[] buffer = new byte[extBlocks ? 5 : 4];
|
||||
WriteBlockPermission(raw, place, delete, extBlocks, buffer, 0);
|
||||
return buffer;
|
||||
}
|
||||
|
@ -193,8 +193,13 @@ namespace MCGalaxy {
|
||||
AccessResult access = level.BuildAccess.Check(this);
|
||||
AllowBuild = access == AccessResult.Whitelisted || access == AccessResult.Allowed;
|
||||
|
||||
try {
|
||||
Send(Packet.LevelInitalise());
|
||||
try {
|
||||
if (Supports(CpeExt.FastMap)) {
|
||||
int volume = level.blocks.Length;
|
||||
Send(Packet.LevelInitaliseExt(volume));
|
||||
} else {
|
||||
Send(Packet.LevelInitalise());
|
||||
}
|
||||
|
||||
if (hasBlockDefs) {
|
||||
if (oldLevel != null && oldLevel != level) {
|
||||
@ -207,8 +212,9 @@ namespace MCGalaxy {
|
||||
}
|
||||
}
|
||||
|
||||
using (LevelChunkStream s = new LevelChunkStream(this))
|
||||
using (LevelChunkStream s = new LevelChunkStream(this)) {
|
||||
LevelChunkStream.CompressMap(this, s);
|
||||
}
|
||||
|
||||
// Force players to read the MOTD (clamped to 3 seconds at most)
|
||||
if (level.Config.LoadDelay > 0)
|
||||
|
@ -36,7 +36,8 @@ namespace MCGalaxy.Network {
|
||||
public override long Seek(long offset, SeekOrigin origin) { throw ex; }
|
||||
public override void SetLength(long length) { throw ex; }
|
||||
|
||||
internal int index, position, length;
|
||||
int index;
|
||||
byte chunkValue;
|
||||
Player p;
|
||||
byte[] data = new byte[chunkSize + 4];
|
||||
const int chunkSize = 1024;
|
||||
@ -77,12 +78,24 @@ namespace MCGalaxy.Network {
|
||||
void WritePacket() {
|
||||
data[0] = Opcode.LevelDataChunk;
|
||||
NetUtils.WriteU16((ushort)index, data, 1);
|
||||
data[1027] = (byte)(100 * (float)position / length);
|
||||
data[1027] = chunkValue;
|
||||
p.Send(data);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
|
||||
static Stream CompressMapHeader(Player player, int volume, LevelChunkStream dst) {
|
||||
Stream stream = null;
|
||||
if (player.Supports(CpeExt.FastMap)) {
|
||||
stream = new DeflateStream(dst, CompressionMode.Compress, true);
|
||||
} else {
|
||||
stream = new GZipStream(dst, CompressionMode.Compress, true);
|
||||
byte[] buffer = new byte[4]; NetUtils.WriteI32(volume, buffer, 0);
|
||||
stream.Write(buffer, 0, sizeof(int));
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
public unsafe static void CompressMap(Player p, LevelChunkStream dst) {
|
||||
const int bufferSize = 64 * 1024;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
@ -109,7 +122,7 @@ namespace MCGalaxy.Network {
|
||||
|
||||
// Players with block defs don't need fallbacks for first 256 blocks
|
||||
if (block < Block.Count && p.hasBlockDefs) { conv[b] = (byte)block; continue; }
|
||||
|
||||
|
||||
// Use custom block fallback, if possible
|
||||
BlockDefinition def = p.level.CustomBlockDefs[block];
|
||||
if (def == null) {
|
||||
@ -128,12 +141,10 @@ namespace MCGalaxy.Network {
|
||||
|
||||
Level lvl = p.level;
|
||||
bool hasBlockDefs = p.hasBlockDefs;
|
||||
using (GZipStream gs = new GZipStream(dst, CompressionMode.Compress, true)) {
|
||||
byte[] blocks = lvl.blocks;
|
||||
NetUtils.WriteI32(blocks.Length, buffer, 0);
|
||||
gs.Write(buffer, 0, sizeof(int));
|
||||
dst.length = blocks.Length;
|
||||
|
||||
byte[] blocks = lvl.blocks;
|
||||
float progScale = 100.0f / blocks.Length;
|
||||
|
||||
using (Stream stream = CompressMapHeader(p, blocks.Length, dst)) {
|
||||
// compress the map data in 64 kb chunks
|
||||
#if TEN_BIT_BLOCKS
|
||||
if (p.hasExtBlocks) {
|
||||
@ -155,8 +166,8 @@ namespace MCGalaxy.Network {
|
||||
|
||||
bIndex += 2;
|
||||
if (bIndex == bufferSize) {
|
||||
dst.position = i;
|
||||
gs.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
dst.chunkValue = (byte)(i * progScale);
|
||||
stream.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
}
|
||||
}
|
||||
} else if (p.hasBlockDefs) {
|
||||
@ -174,8 +185,8 @@ namespace MCGalaxy.Network {
|
||||
|
||||
bIndex++;
|
||||
if (bIndex == bufferSize) {
|
||||
dst.position = i;
|
||||
gs.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
dst.chunkValue = (byte)(i * progScale);
|
||||
stream.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -192,8 +203,8 @@ namespace MCGalaxy.Network {
|
||||
|
||||
bIndex++;
|
||||
if (bIndex == bufferSize) {
|
||||
dst.position = i;
|
||||
gs.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
dst.chunkValue = (byte)(i * progScale);
|
||||
stream.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -209,8 +220,8 @@ namespace MCGalaxy.Network {
|
||||
|
||||
bIndex++;
|
||||
if (bIndex == bufferSize) {
|
||||
dst.position = i;
|
||||
gs.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
dst.chunkValue = (byte)(i * progScale);
|
||||
stream.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -223,15 +234,14 @@ namespace MCGalaxy.Network {
|
||||
|
||||
bIndex++;
|
||||
if (bIndex == bufferSize) {
|
||||
dst.position = i;
|
||||
gs.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
dst.chunkValue = (byte)(i * progScale);
|
||||
stream.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (bIndex > 0) gs.Write(buffer, 0, bIndex);
|
||||
|
||||
if (bIndex > 0) stream.Write(buffer, 0, bIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ namespace MCGalaxy {
|
||||
new ExtEntry(CpeExt.EnvMapAspect), new ExtEntry(CpeExt.PlayerClick),
|
||||
new ExtEntry(CpeExt.EntityProperty), new ExtEntry(CpeExt.ExtEntityPositions),
|
||||
new ExtEntry(CpeExt.TwoWayPing), new ExtEntry(CpeExt.InventoryOrder),
|
||||
new ExtEntry(CpeExt.InstantMOTD),
|
||||
new ExtEntry(CpeExt.InstantMOTD), new ExtEntry(CpeExt.FastMap),
|
||||
#if TEN_BIT_BLOCKS
|
||||
new ExtEntry(CpeExt.ExtBlocks),
|
||||
#endif
|
||||
@ -204,6 +204,7 @@ namespace MCGalaxy {
|
||||
public const string TwoWayPing = "TwoWayPing";
|
||||
public const string InventoryOrder = "InventoryOrder";
|
||||
public const string InstantMOTD = "InstantMOTD";
|
||||
public const string FastMap = "FastMap";
|
||||
public const string ExtBlocks = "ExtBlocks";
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user