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 FastColour[] FogColour;
public static Vector3[] MinBB, MaxBB, RenderMinBB, RenderMaxBB; public static Vector3[] MinBB, MaxBB, RenderMinBB, RenderMaxBB;
static uint[] DefinedCustomBlocks; static uint[] DefinedCustomBlocks;
public static int MaxDefined, Count, IDMask; public static int MaxUsed, Count, IDMask;
public static void Allocate(int count) { public static void Allocate(int count) {
IsLiquid = new bool[count]; IsLiquid = new bool[count];
@ -100,9 +100,13 @@ namespace ClassicalSharp {
RenderMaxBB = new Vector3[count]; RenderMaxBB = new Vector3[count];
DefinedCustomBlocks = new uint[count >> 5]; DefinedCustomBlocks = new uint[count >> 5];
MaxDefined = count - 1;
Count = count; 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() { public static void Reset() {

View File

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

View File

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

View File

@ -117,7 +117,7 @@ namespace ClassicalSharp.Map {
BlockRaw[] blocks = world.blocks; BlockRaw[] blocks = world.blocks;
// Update if any blocks in the chunk are affected by light change // 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) { for (; y >= minY; y--, i -= world.OneY) {
BlockID other = blocks[i]; BlockID other = blocks[i];
bool affected = y == nY ? Needs(block, other) : BlockInfo.Draw[other] != DrawType.Gas; 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); int elemsLeft = InitialHeightmapCoverage(x1, z1, xCount, zCount, skip);
#if !ONLY_8BIT #if !ONLY_8BIT
if (BlockInfo.MaxDefined >= 256) { if (BlockInfo.MaxUsed >= 256) {
fixed (BlockRaw* mapPtr2 = game.World.blocks2) { fixed (BlockRaw* mapPtr2 = game.World.blocks2) {
if (!CalculateHeightmapCoverage_16Bit(x1, z1, xCount, zCount, elemsLeft, skip, mapPtr, mapPtr2)) { if (!CalculateHeightmapCoverage_16Bit(x1, z1, xCount, zCount, elemsLeft, skip, mapPtr, mapPtr2)) {
FinishHeightmapCoverage(x1, z1, xCount, zCount, skip); 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) { public void SetBlock(int x, int y, int z, BlockID blockId) {
int i = (y * Length + z) * Width + x; int i = (y * Length + z) * Width + x;
blocks[i] = (BlockRaw)blockId; 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); blocks2[i] = (BlockRaw)(blockId >> 8);
} }

View File

@ -48,7 +48,7 @@ namespace ClassicalSharp {
bool allSolid = false; bool allSolid = false;
fixed (BlockRaw* mapPtr = map.blocks) { fixed (BlockRaw* mapPtr = map.blocks) {
#if !ONLY_8BIT #if !ONLY_8BIT
if (BlockInfo.MaxDefined >= 256) { if (BlockInfo.MaxUsed >= 256) {
ReadChunkData_16Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid); ReadChunkData_16Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid);
} else { } else {
ReadChunkData_8Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid); 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; reader.ExtendedPositions = false; reader.ExtendedBlocks = false;
writer.ExtendedPositions = false; writer.ExtendedBlocks = false; writer.ExtendedPositions = false; writer.ExtendedBlocks = false;
BlockInfo.SetMaxUsed(255);
} }
internal Action[] handlers = new Action[256]; internal Action[] handlers = new Action[256];

View File

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

View File

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

View File

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

View File

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

View File

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