avoid blocks2 allocation in some cases

This commit is contained in:
UnknownShadow200 2018-04-06 12:07:02 +10:00
parent 7e92d18f40
commit 30f5ae7947
13 changed files with 55 additions and 43 deletions

View File

@ -70,7 +70,7 @@ namespace ClassicalSharp {
public static FastColour[] FogColour;
public static Vector3[] MinBB, MaxBB, RenderMinBB, RenderMaxBB;
static uint[] DefinedCustomBlocks;
public static int MaxDefined, Count, IDMask;
public static int MaxUsed, Count, IDMask;
public static void Allocate(int count) {
IsLiquid = new bool[count];
@ -100,9 +100,13 @@ namespace ClassicalSharp {
RenderMaxBB = new Vector3[count];
DefinedCustomBlocks = new uint[count >> 5];
MaxDefined = count - 1;
Count = count;
IDMask = Utils.NextPowerOf2(Count) - 1;
SetMaxUsed(count - 1);
}
public static void SetMaxUsed(int max) {
MaxUsed = max;
IDMask = Utils.NextPowerOf2(max + 1) - 1;
}
public static void Reset() {

View File

@ -123,7 +123,7 @@ namespace ClassicalSharp.Entities {
ModelBlock = Block.Air;
BlockID block;
if (BlockID.TryParse(ModelName, out block) && block <= BlockInfo.MaxDefined) {
if (BlockID.TryParse(ModelName, out block) && block < BlockInfo.Count) {
ModelName = "block";
ModelBlock = block;
}

View File

@ -12,7 +12,7 @@ namespace ClassicalSharp.Map {
int i = (maxY * length + z) * width + x;
BlockRaw[] blocks = game.World.blocks;
if (BlockInfo.MaxDefined < 256) {
if (BlockInfo.MaxUsed < 256) {
for (int y = maxY; y >= 0; y--, i -= oneY) {
int block = blocks[i];
if (BlockInfo.BlocksLight[block]) {

View File

@ -117,7 +117,7 @@ namespace ClassicalSharp.Map {
BlockRaw[] blocks = world.blocks;
// Update if any blocks in the chunk are affected by light change
if (BlockInfo.MaxDefined < 256) {
if (BlockInfo.MaxUsed < 256) {
for (; y >= minY; y--, i -= world.OneY) {
BlockID other = blocks[i];
bool affected = y == nY ? Needs(block, other) : BlockInfo.Draw[other] != DrawType.Gas;

View File

@ -71,7 +71,7 @@ namespace ClassicalSharp.Map {
int elemsLeft = InitialHeightmapCoverage(x1, z1, xCount, zCount, skip);
#if !ONLY_8BIT
if (BlockInfo.MaxDefined >= 256) {
if (BlockInfo.MaxUsed >= 256) {
fixed (BlockRaw* mapPtr2 = game.World.blocks2) {
if (!CalculateHeightmapCoverage_16Bit(x1, z1, xCount, zCount, elemsLeft, skip, mapPtr, mapPtr2)) {
FinishHeightmapCoverage(x1, z1, xCount, zCount, skip);

View File

@ -66,7 +66,13 @@ namespace ClassicalSharp.Map {
public void SetBlock(int x, int y, int z, BlockID blockId) {
int i = (y * Length + z) * Width + x;
blocks[i] = (BlockRaw)blockId;
if (blocks == blocks2) return;
// defer allocation of second map array if possible
if (blocks == blocks2) {
if (blockId < 256) return;
blocks2 = new BlockRaw[blocks.Length];
BlockInfo.SetMaxUsed(767);
}
blocks2[i] = (BlockRaw)(blockId >> 8);
}

View File

@ -48,7 +48,7 @@ namespace ClassicalSharp {
bool allSolid = false;
fixed (BlockRaw* mapPtr = map.blocks) {
#if !ONLY_8BIT
if (BlockInfo.MaxDefined >= 256) {
if (BlockInfo.MaxUsed >= 256) {
ReadChunkData_16Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid);
} else {
ReadChunkData_8Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid);

View File

@ -198,6 +198,7 @@ namespace ClassicalSharp.Network {
reader.ExtendedPositions = false; reader.ExtendedBlocks = false;
writer.ExtendedPositions = false; writer.ExtendedBlocks = false;
BlockInfo.SetMaxUsed(255);
}
internal Action[] handlers = new Action[256];

View File

@ -324,13 +324,14 @@ namespace ClassicalSharp.Network.Protocols {
int value = reader.ReadInt32();
WorldEnv env = game.World.Env;
Utils.Clamp(ref value, -0xFFFFFF, 0xFFFFFF);
int maxBlock = BlockInfo.Count - 1;
switch (type) {
case 0:
Utils.Clamp(ref value, 0, BlockInfo.MaxDefined);
Utils.Clamp(ref value, 0, maxBlock);
env.SetSidesBlock((BlockID)value); break;
case 1:
Utils.Clamp(ref value, 0, BlockInfo.MaxDefined);
Utils.Clamp(ref value, 0, maxBlock);
env.SetEdgeBlock((BlockID)value); break;
case 2:
env.SetEdgeLevel(value); break;

View File

@ -46,7 +46,7 @@ namespace ClassicalSharp.Network.Protocols {
DateTime mapReceiveStart;
DeflateStream gzipStream;
GZipHeaderReader gzipHeader;
int mapSizeIndex, mapIndex;
int mapSizeIndex, mapIndex, mapVolume;
byte[] mapSize = new byte[4], map;
FixedBufferStream mapPartStream;
Screen prevScreen;
@ -78,13 +78,10 @@ namespace ClassicalSharp.Network.Protocols {
// Fast map puts volume in header, doesn't bother with gzip
if (net.cpeData.fastMap) {
int size = reader.ReadInt32();
mapVolume = reader.ReadInt32();
gzipHeader.done = true;
mapSizeIndex = 4;
map = new byte[size];
#if !ONLY_8BIT
if (reader.ExtendedBlocks) map2 = new byte[size];
#endif
map = new byte[mapVolume];
}
}
@ -150,15 +147,14 @@ namespace ClassicalSharp.Network.Protocols {
if (mapSizeIndex == 4) {
if (map == null) {
int size = mapSize[0] << 24 | mapSize[1] << 16 | mapSize[2] << 8 | mapSize[3];
map = new byte[size];
#if !ONLY_8BIT
if (reader.ExtendedBlocks) map2 = new byte[size];
#endif
mapVolume = mapSize[0] << 24 | mapSize[1] << 16 | mapSize[2] << 8 | mapSize[3];
map = new byte[mapVolume];
}
#if !ONLY_8BIT
if (reader.ExtendedBlocks && value != 0) {
// Only allocate map2 when needed
if (map2 == null) map2 = new byte[mapVolume];
mapIndex2 += gzipStream2.Read(map2, mapIndex2, map2.Length - mapIndex2);
} else {
mapIndex += gzipStream.Read(map, mapIndex, map.Length - mapIndex);
@ -181,7 +177,7 @@ namespace ClassicalSharp.Network.Protocols {
}
prevScreen = null;
int mapWidth = reader.ReadUInt16();
int mapWidth = reader.ReadUInt16();
int mapHeight = reader.ReadUInt16();
int mapLength = reader.ReadUInt16();
@ -190,7 +186,11 @@ namespace ClassicalSharp.Network.Protocols {
game.World.SetNewMap(map, mapWidth, mapHeight, mapLength);
#if !ONLY_8BIT
if (reader.ExtendedBlocks) game.World.blocks2 = map2;
if (reader.ExtendedBlocks) {
// defer allocation of scond map array if possible
game.World.blocks2 = map2 == null ? map : map2;
BlockInfo.SetMaxUsed(map2 == null ? 255 : 767);
}
#endif
game.WorldEvents.RaiseOnNewMapLoaded();
net.wom.CheckSendWomID();

View File

@ -161,7 +161,7 @@ namespace ClassicalSharp.Renderers {
int i = (maxY * length + z) * width + x;
BlockRaw[] blocks = map.blocks;
if (BlockInfo.MaxDefined < 256) {
if (BlockInfo.MaxUsed < 256) {
for (int y = maxY; y >= 0; y--, i -= oneY) {
byte draw = BlockInfo.Draw[blocks[i]];
if (!(draw == DrawType.Gas || draw == DrawType.Sprite)) {

View File

@ -31,28 +31,28 @@ typedef struct GuiElementVTABLE_ {
typedef struct GuiElement_ { GuiElementVTABLE* VTABLE; } GuiElement;
void GuiElement_Reset(GuiElement* elem);
/*
HandlesAllInput; / Whether this screen handles all input. Prevents user interacting with the world
BlocksWorld; / Whether this screen completely and opaquely covers the game world behind it
HidesHUD; / Whether this screen hides the normal in-game HUD
RenderHUDOver; / Whether the normal in-game HUD should be drawn over the top of this screen */
#define Screen_Layout GuiElementVTABLE* VTABLE; bool HandlesAllInput, BlocksWorld; \
bool HidesHUD, RenderHUDOver; void (*OnResize)(GuiElement* elem);
#define Screen_Layout GuiElementVTABLE* VTABLE; \
bool HandlesAllInput; /* Whether this screen handles all input. Prevents user interacting with the world */ \
bool BlocksWorld; /* Whether this screen completely and opaquely covers the game world behind it */ \
bool HidesHUD; /* Whether this screen hides the normal in-game HUD */ \
bool RenderHUDOver; /* Whether the normal in-game HUD should be drawn over the top of this screen */ \
void (*OnResize)(GuiElement* elem);
/* Represents a container of widgets and other 2D elements. May cover entire window. */
typedef struct Screen_ { Screen_Layout } Screen;
void Screen_Reset(Screen* screen);
/*
X, Y, Width, Height; / Top left corner, and dimensions, of this widget
Active; / Whether this widget is currently being moused over
Disabled; / Whether widget is prevented from being interacted with
HorAnchor, VerAnchor; / Specifies the reference point for when this widget is resized
XOffset, YOffset; / Offset from the reference point */
typedef void (*Widget_LeftClick)(GuiElement* screenElem, GuiElement* widget);
#define Widget_Layout GuiElementVTABLE* VTABLE; Int32 X, Y, Width, Height; bool Active, Disabled; \
UInt8 HorAnchor, VerAnchor; Int32 XOffset, YOffset; void (*Reposition)(GuiElement* elem); Widget_LeftClick MenuClick;
#define Widget_Layout GuiElementVTABLE* VTABLE; \
Int32 X, Y, Width, Height; /* Top left corner, and dimensions, of this widget */ \
bool Active; /* Whether this widget is currently being moused over*/ \
bool Disabled; /* Whether widget is prevented from being interacted with */ \
UInt8 HorAnchor, VerAnchor; /* Specifies the reference point for when this widget is resized */ \
Int32 XOffset, YOffset; /* Offset from the reference point */ \
void (*Reposition)(GuiElement* elem); \
Widget_LeftClick MenuClick;
/* Represents an individual 2D gui component. */
typedef struct Widget_ { Widget_Layout } Widget;
@ -60,6 +60,7 @@ void Widget_DoReposition(GuiElement* elem);
void Widget_Init(Widget* widget);
bool Widget_Contains(Widget* widget, Int32 x, Int32 y);
GfxResourceID Gui_GuiTex, Gui_GuiClassicTex, Gui_IconsTex;
Screen* Gui_HUD;
Screen* Gui_Active;

View File

@ -588,9 +588,8 @@ void TableWidget_MakeDescTex(TableWidget* widget, BlockID block) {
TableWidget_UpdateDescTexPos(widget);
}
bool TableWidget_RowEmpty(Int32 i) {
BlockID[] map = game.Inventory.Map;
int max = Math.Min(i + ElementsPerRow, map.Length);
bool TableWidget_RowEmpty(TableWidget* widget, Int32 i) {
Int32 max = min(i + widget->ElementsPerRow, (Int32)Array_Elems(Inventory_Map));
Int32 j;
for (j = i; j < max; j++) {