diff --git a/ClassicalSharp/Commands/CommandList.cs b/ClassicalSharp/Commands/CommandList.cs
index 94cc11d2a..35748e668 100644
--- a/ClassicalSharp/Commands/CommandList.cs
+++ b/ClassicalSharp/Commands/CommandList.cs
@@ -16,12 +16,12 @@ namespace ClassicalSharp.Commands {
public class CommandList : IGameComponent {
- const string prefix = "/client";
+ const string prefix = "/client", prefixSpace = "/client ";
public bool IsCommandPrefix(string input) {
if (game.Server.IsSinglePlayer && Utils.CaselessStarts(input, "/"))
return true;
- return Utils.CaselessStarts(input, prefix + " ")
+ return Utils.CaselessStarts(input, prefixSpace)
|| Utils.CaselessEquals(input, prefix);
}
@@ -75,8 +75,10 @@ namespace ClassicalSharp.Commands {
static char[] splitChar = { ' ' };
public void Execute(string text) {
- if (Utils.CaselessStarts(text, prefix)) { // /client command args
- text = text.Substring(prefix.Length).TrimStart(splitChar);
+ if (Utils.CaselessStarts(text, prefixSpace)) { // /client command args
+ text = text.Substring(prefixSpace.Length);
+ } else if (Utils.CaselessStarts(text, prefix)) { // /clientcommand args
+ text = text.Substring(prefix.Length);
} else { // /command args
text = text.Substring(1);
}
diff --git a/ClassicalSharp/Commands/Commands.cs b/ClassicalSharp/Commands/Commands.cs
index adf1d48a1..56b7e23c2 100644
--- a/ClassicalSharp/Commands/Commands.cs
+++ b/ClassicalSharp/Commands/Commands.cs
@@ -168,15 +168,16 @@ namespace ClassicalSharp.Commands {
if (args.Length == 1) return true;
if (Utils.CaselessEquals(args[1], "yes")) { persist = true; return true; }
- int temp = -1;
+ int temp = BlockInfo.FindID(args[1]);
BlockID block = 0;
- if ((temp = BlockInfo.FindID(args[1])) != -1) {
+
+ if (temp != -1) {
block = (BlockID)temp;
} else if (!BlockID.TryParse(args[1], out block)) {
game.Chat.Add("&eCuboid: &c\"" + args[1] + "\" is not a valid block name or id."); return false;
}
- if (block >= Block.CpeCount && BlockInfo.Name[block] == "Invalid") {
+ if (block >= Block.CpeCount && !BlockInfo.IsCustomDefined(block)) {
game.Chat.Add("&eCuboid: &cThere is no block with id \"" + args[1] + "\"."); return false;
}
this.block = block;
diff --git a/ClassicalSharp/Map/World.cs b/ClassicalSharp/Map/World.cs
index 81add5e34..6228ee729 100644
--- a/ClassicalSharp/Map/World.cs
+++ b/ClassicalSharp/Map/World.cs
@@ -76,13 +76,6 @@ namespace ClassicalSharp.Map {
return blocks[(p.Y * Length + p.Z) * Width + p.X];
}
- /// Returns the block at the given world coordinates with bounds checking,
- /// returning 0 is the coordinates were outside the map.
- public BlockID SafeGetBlock(int x, int y, int z) {
- return IsValidPos(x, y, z) ?
- blocks[(y * Length + z) * Width + x] : Block.Air;
- }
-
/// Returns the block at the given world coordinates with bounds checking,
/// returning 0 is the coordinates were outside the map.
public BlockID SafeGetBlock(Vector3I p) {
diff --git a/ClassicalSharp/Math/PickedPos.cs b/ClassicalSharp/Math/PickedPos.cs
index f640ca053..af0c51522 100644
--- a/ClassicalSharp/Math/PickedPos.cs
+++ b/ClassicalSharp/Math/PickedPos.cs
@@ -26,7 +26,7 @@ namespace ClassicalSharp {
public Vector3I BlockPos;
/// Integer world coordinates of the neighbouring block that is closest to the player.
- public Vector3I TranslatedPos { get { return BlockPos + offsets[(byte)Face]; } }
+ public Vector3I TranslatedPos;
/// Whether this instance actually has a selected block currently.
public bool Valid = true;
@@ -41,11 +41,11 @@ namespace ClassicalSharp {
/// calculates the closest face of the selected block's position.
public void SetAsValid(int x, int y, int z, Vector3 min, Vector3 max,
BlockID block, Vector3 intersect) {
- Min = min;
- Max = max;
- BlockPos = new Vector3I(x, y, z);
+ Vector3I pos = new Vector3I(x, y, z);
Valid = true;
+ BlockPos = pos;
Block = block;
+ Min = min; Max = max;
Intersect = intersect;
float dist = float.PositiveInfinity;
@@ -55,26 +55,31 @@ namespace ClassicalSharp {
TestAxis(intersect.Y - Max.Y, ref dist, BlockFace.YMax);
TestAxis(intersect.Z - Min.Z, ref dist, BlockFace.ZMin);
TestAxis(intersect.Z - Max.Z, ref dist, BlockFace.ZMax);
+
+ switch (Face) {
+ case BlockFace.XMin: pos.X--; break;
+ case BlockFace.XMax: pos.X++; break;
+ case BlockFace.YMin: pos.Y--; break;
+ case BlockFace.YMax: pos.Y++; break;
+ case BlockFace.ZMin: pos.Z--; break;
+ case BlockFace.ZMax: pos.Z++; break;
+ }
+ TranslatedPos = pos;
}
/// Mark this as not having a selected block.
public void SetAsInvalid() {
Valid = false;
BlockPos = Vector3I.MinusOne;
- Face = (BlockFace)6;
Block = 0;
+ TranslatedPos = Vector3I.MinusOne;
+ Face = (BlockFace)6;
}
void TestAxis(float dAxis, ref float dist, BlockFace fAxis) {
dAxis = Math.Abs(dAxis);
- if (dAxis >= dist) return;
+ if (dAxis >= dist) return;
dist = dAxis; Face = fAxis;
}
-
- static Vector3I[] offsets = new Vector3I[] {
- Vector3I.UnitX, -Vector3I.UnitX, Vector3I.UnitY,
- -Vector3I.UnitY, Vector3I.UnitZ, -Vector3I.UnitZ,
- Vector3I.Zero,
- };
}
}
\ No newline at end of file
diff --git a/ClassicalSharp/Network/Protocols/CPE.cs b/ClassicalSharp/Network/Protocols/CPE.cs
index 35e5509b3..b2340c0b2 100644
--- a/ClassicalSharp/Network/Protocols/CPE.cs
+++ b/ClassicalSharp/Network/Protocols/CPE.cs
@@ -151,22 +151,22 @@ namespace ClassicalSharp.Network.Protocols {
void HandleMakeSelection() {
byte selectionId = reader.ReadUInt8();
string label = reader.ReadString();
- Vector3I start, end;
- start.X = reader.ReadInt16();
- start.Y = reader.ReadInt16();
- start.Z = reader.ReadInt16();
+ Vector3I p1;
+ p1.X = reader.ReadInt16();
+ p1.Y = reader.ReadInt16();
+ p1.Z = reader.ReadInt16();
- end.X = reader.ReadInt16();
- end.Y = reader.ReadInt16();
- end.Z = reader.ReadInt16();
+ Vector3I p2;
+ p2.X = reader.ReadInt16();
+ p2.Y = reader.ReadInt16();
+ p2.Z = reader.ReadInt16();
byte r = (byte)reader.ReadInt16();
byte g = (byte)reader.ReadInt16();
byte b = (byte)reader.ReadInt16();
byte a = (byte)reader.ReadInt16();
- Vector3I p1 = Vector3I.Min(start, end), p2 = Vector3I.Max(start, end);
FastColour col = new FastColour(r, g, b, a);
game.SelectionManager.AddSelection(selectionId, p1, p2, col);
}
diff --git a/ClassicalSharp/Selections/SelectionBox.cs b/ClassicalSharp/Selections/SelectionBox.cs
index fa0a54cd6..e1596e1b1 100644
--- a/ClassicalSharp/Selections/SelectionBox.cs
+++ b/ClassicalSharp/Selections/SelectionBox.cs
@@ -13,9 +13,9 @@ namespace ClassicalSharp.Selections {
public FastColour Colour;
public float MinDist, MaxDist;
- public SelectionBox(Vector3I start, Vector3I end, FastColour col) {
- Min = Vector3I.Min(start, end);
- Max = Vector3I.Max(start, end);
+ public SelectionBox(Vector3I p1, Vector3I p2, FastColour col) {
+ Min = Vector3I.Min(p1, p2);
+ Max = Vector3I.Max(p1, p2);
Colour = col;
}
diff --git a/ClassicalSharp/Singleplayer/LiquidPhysics.cs b/ClassicalSharp/Singleplayer/LiquidPhysics.cs
index 7b5b65723..d2e2d2222 100644
--- a/ClassicalSharp/Singleplayer/LiquidPhysics.cs
+++ b/ClassicalSharp/Singleplayer/LiquidPhysics.cs
@@ -163,9 +163,12 @@ namespace ClassicalSharp.Singleplayer {
for (int zz = z - 2; zz <= z + 2; zz++)
for (int xx = x - 2; xx <= x + 2; xx++)
{
- block = map.SafeGetBlock(xx, yy, zz);
- if (block == Block.Water || block == Block.StillWater)
+ if (!map.IsValidPos(xx, yy, zz)) continue;
+
+ block = map.blocks[xx + width * (zz + yy * length)];
+ if (block == Block.Water || block == Block.StillWater) {
game.UpdateBlock(xx, yy, zz, Block.Air);
+ }
}
}
@@ -184,8 +187,9 @@ namespace ClassicalSharp.Singleplayer {
index = xx + width * (zz + yy * length);
block = map.blocks[index];
- if (block == Block.Water || block == Block.StillWater)
+ if (block == Block.Water || block == Block.StillWater) {
Water.Enqueue((1u << tickShift) | (uint)index);
+ }
}
}
}
diff --git a/ClassicalSharp/Utils/Vector3I.cs b/ClassicalSharp/Utils/Vector3I.cs
index 88cfc7b86..5e26a581f 100644
--- a/ClassicalSharp/Utils/Vector3I.cs
+++ b/ClassicalSharp/Utils/Vector3I.cs
@@ -6,11 +6,6 @@ namespace ClassicalSharp {
/// Represents a 3D integer vector.
public struct Vector3I {
-
- public static Vector3I Zero = new Vector3I(0, 0, 0);
- public static Vector3I UnitX = new Vector3I(1, 0, 0);
- public static Vector3I UnitY = new Vector3I(0, 1, 0);
- public static Vector3I UnitZ = new Vector3I(0, 0, 1);
public static Vector3I MinusOne = new Vector3I(-1, -1, -1);
public int X, Y, Z;
@@ -23,22 +18,6 @@ namespace ClassicalSharp {
X = value; Y = value; Z = value;
}
- public static Vector3I operator * (Vector3I left, int right) {
- return new Vector3I(left.X * right, left.Y * right, left.Z * right);
- }
-
- public static Vector3I operator + (Vector3I left, Vector3I right) {
- return new Vector3I(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
- }
-
- public static Vector3I operator - (Vector3I left, Vector3I right) {
- return new Vector3I(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
- }
-
- public static Vector3I operator - (Vector3I left) {
- return new Vector3I(-left.X, -left.Y, -left.Z);
- }
-
public static explicit operator Vector3(Vector3I value) {
return new Vector3(value.X, value.Y, value.Z);
}
diff --git a/src/Client/Chat.c b/src/Client/Chat.c
index 24a68a6e1..72e7d1836 100644
--- a/src/Client/Chat.c
+++ b/src/Client/Chat.c
@@ -5,6 +5,12 @@
#include "Game.h"
#include "ErrorHandler.h"
#include "ServerConnection.h"
+#include "World.h"
+#include "Inventory.h"
+#include "Player.h"
+#include "Window.h"
+#include "GraphicsAPI.h"
+#include "Funcs.h"
void ChatLine_Make(ChatLine* line, STRING_TRANSIENT String* text) {
String dst = String_InitAndClearArray(line->Buffer);
@@ -17,17 +23,6 @@ String Chat_LogName = String_FromEmptyArray(Chat_LogNameBuffer);
Stream Chat_LogStream;
DateTime ChatLog_LastLogDate;
-void Chat_Send(STRING_PURE String* text) {
- if (text->length == 0) return;
- StringsBuffer_Add(&InputLog, text);
-
- if (Commands_IsCommandPrefix(text)) {
- Commands_Execute(text);
- } else {
- ServerConnection_SendChat(text);
- }
-}
-
void Chat_CloseLog(void) {
if (Chat_LogStream.Data == NULL) return;
ReturnCode code = Chat_LogStream.Close(&Chat_LogStream);
@@ -123,32 +118,22 @@ void Chat_AppendLog(STRING_PURE String* text) {
}
void Chat_Add(STRING_PURE String* text) { Chat_AddOf(text, MESSAGE_TYPE_NORMAL); }
-void Chat_AddOf(STRING_PURE String* text, MessageType type) {
- if (type == MESSAGE_TYPE_NORMAL) {
+void Chat_AddOf(STRING_PURE String* text, Int32 msgType) {
+ if (msgType == MESSAGE_TYPE_NORMAL) {
StringsBuffer_Add(&ChatLog, text);
Chat_AppendLog(text);
- } else if (type >= MESSAGE_TYPE_STATUS_1 && type <= MESSAGE_TYPE_STATUS_3) {
- ChatLine_Make(&Chat_Status[type - MESSAGE_TYPE_STATUS_1], text);
- } else if (type >= MESSAGE_TYPE_BOTTOMRIGHT_1 && type <= MESSAGE_TYPE_BOTTOMRIGHT_3) {
- ChatLine_Make(&Chat_BottomRight[type - MESSAGE_TYPE_BOTTOMRIGHT_1], text);
- } else if (type == MESSAGE_TYPE_ANNOUNCEMENT) {
+ } else if (msgType >= MESSAGE_TYPE_STATUS_1 && msgType <= MESSAGE_TYPE_STATUS_3) {
+ ChatLine_Make(&Chat_Status[msgType - MESSAGE_TYPE_STATUS_1], text);
+ } else if (msgType >= MESSAGE_TYPE_BOTTOMRIGHT_1 && msgType <= MESSAGE_TYPE_BOTTOMRIGHT_3) {
+ ChatLine_Make(&Chat_BottomRight[msgType - MESSAGE_TYPE_BOTTOMRIGHT_1], text);
+ } else if (msgType == MESSAGE_TYPE_ANNOUNCEMENT) {
ChatLine_Make(&Chat_Announcement, text);
- } else if (type >= MESSAGE_TYPE_CLIENTSTATUS_1 && type <= MESSAGE_TYPE_CLIENTSTATUS_3) {
- ChatLine_Make(&Chat_ClientStatus[type - MESSAGE_TYPE_CLIENTSTATUS_1], text);
+ } else if (msgType >= MESSAGE_TYPE_CLIENTSTATUS_1 && msgType <= MESSAGE_TYPE_CLIENTSTATUS_3) {
+ ChatLine_Make(&Chat_ClientStatus[msgType - MESSAGE_TYPE_CLIENTSTATUS_1], text);
}
- Event_RaiseChat(&ChatEvents_ChatReceived, text, type);
+ Event_RaiseChat(&ChatEvents_ChatReceived, text, msgType);
}
-void Chat_Reset(void) {
- Chat_CloseLog();
- String_Clear(&Chat_LogName);
-}
-
-IGameComponent Chat_MakeGameComponent(void) {
- IGameComponent comp = IGameComponent_MakeEmpty();
- comp.Reset = Chat_Reset;
- return comp;
-}
typedef struct ChatCommand_ {
String Name;
@@ -159,24 +144,124 @@ typedef struct ChatCommand_ {
typedef void (*ChatCommandConstructor)(ChatCommand* cmd);
#define COMMANDS_PREFIX "/client"
-#define COMMANDS_PREFIX_STARTS "/client "
+#define COMMANDS_PREFIX_SPACE "/client "
+#define Chat_AddRaw(str, raw) String str = String_FromConst(raw); Chat_Add(&str);
+
+ChatCommand commands_list[8];
+UInt32 commands_count;
+
bool Commands_IsCommandPrefix(STRING_PURE String* input) {
if (input->length == 0) return false;
if (ServerConnection_IsSinglePlayer && input->buffer[0] == '/')
return true;
- String starts = String_FromConst(COMMANDS_PREFIX_STARTS);
- String prefix = String_FromConst(COMMANDS_PREFIX);
- return String_CaselessStarts(input, &starts)
+ String prefixSpace = String_FromConst(COMMANDS_PREFIX_SPACE);
+ String prefix = String_FromConst(COMMANDS_PREFIX);
+ return String_CaselessStarts(input, &prefixSpace)
|| String_CaselessEquals(input, &prefix);
}
+void Commands_Register(ChatCommandConstructor constructor) {
+ if (commands_count == Array_NumElements(commands_list)) {
+ ErrorHandler_Fail("Commands_Register - hit max client commands");
+ }
+
+ ChatCommand command;
+ Platform_MemSet(&command, 0, sizeof(ChatCommand));
+ constructor(&command);
+ commands_list[commands_count++] = command;
+}
+
+void Commands_Log(const UInt8* raw1, String* str2, const UInt8* raw3) {
+ UInt8 strBuffer[String_BufferSize(STRING_SIZE * 2)];
+ String str = String_InitAndClearArray(strBuffer);
+ String_AppendConst(&str, raw1);
+ String_AppendString(&str, str2);
+ String_AppendConst(&str, raw3);
+ Chat_Add(&str);
+}
+
+ChatCommand* Commands_GetMatch(STRING_PURE String* cmdName) {
+ ChatCommand* match = NULL;
+ UInt32 i;
+ for (i = 0; i < commands_count; i++) {
+ ChatCommand* cmd = &commands_list[i];
+ if (!String_CaselessStarts(&cmd->Name, cmdName)) continue;
+
+ if (match != NULL) {
+ Commands_Log("&e/client: Multiple commands found that start with: \"&f", cmdName, "&e\".");
+ return NULL;
+ }
+ match = cmd;
+ }
+
+ if (match == NULL) {
+ Commands_Log("&e/client: Unrecognised command: \"&f", cmdName, "&e\".");
+ Chat_AddRaw(tmp, "&e/client: Type &a/client &efor a list of commands.");
+ return NULL;
+ }
+ if (match->SingleplayerOnly && !ServerConnection_IsSinglePlayer) {
+ Commands_Log("&e/client: \"&f", cmdName, "&e\" can only be used in singleplayer.");
+ return NULL;
+ }
+ return match;
+}
+
+void Commands_PrintDefined(void) {
+ UInt8 strBuffer[String_BufferSize(STRING_SIZE)];
+ String str = String_InitAndClearArray(strBuffer);
+ UInt32 i;
+
+ for (i = 0; i < commands_count; i++) {
+ ChatCommand* cmd = &commands_list[i];
+ String name = cmd->Name;
+
+ if ((str.length + name.length + 2) > str.capacity) {
+ Chat_Add(&str);
+ String_Clear(&str);
+ }
+ String_AppendString(&str, &name);
+ String_AppendConst(&str, ", ");
+ }
+
+ if (str.length > 0) { Chat_Add(&str); }
+}
+
+void Commands_Execute(STRING_PURE String* input) {
+ String text = *input;
+ String prefixSpace = String_FromConst(COMMANDS_PREFIX_SPACE);
+ String prefix = String_FromConst(COMMANDS_PREFIX);
+
+ if (String_CaselessStarts(&text, &prefixSpace)) { /* /clientcommand args */
+ text = String_UNSAFE_SubstringAt(&text, prefixSpace.length);
+ } else if (String_CaselessStarts(&text, &prefix)) { /* /client command args */
+ text = String_UNSAFE_SubstringAt(&text, prefix.length);
+ } else { /* /command args */
+ text = String_UNSAFE_SubstringAt(&text, 1);
+ }
+
+ if (text.length == 0) { /* only / or /client */
+ Chat_AddRaw(tmp1, "&eList of client commands:");
+ Commands_PrintDefined();
+ Chat_AddRaw(tmp2, "&eTo see help for a command, type &a/client help [cmd name]");
+ return;
+ }
+
+ String args[10];
+ UInt32 argsCount = Array_NumElements(args);
+ String_UNSAFE_Split(&text, ' ', args, &argsCount);
+
+ ChatCommand* cmd = Commands_GetMatch(&args[0]);
+ if (cmd == NULL) return;
+ cmd->Execute(args, argsCount);
+}
+
void HelpCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
if (argsCount == 1) {
- game.Chat.Add("&eList of client commands:");
+ Chat_AddRaw(tmp1, "&eList of client commands:");
Commands_PrintDefined();
- game.Chat.Add("&eTo see help for a command, type /client help [cmd name]");
+ Chat_AddRaw(tmp2, "&eTo see help for a command, type /client help [cmd name]");
} else {
ChatCommand* cmd = Commands_GetMatch(&args[1]);
if (cmd == NULL) return;
@@ -198,9 +283,15 @@ void HelpCommand_Make(ChatCommand* cmd) {
}
void GpuInfoCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
- string[] lines = game.Graphics.ApiInfo;
- for (int i = 0; i < lines.Length; i++) {
- game.Chat.Add("&a" + lines[i]);
+ UInt32 i;
+ for (i = 0; i < Array_NumElements(Gfx_ApiInfo); i++) {
+ if (Gfx_ApiInfo[i].length == 0) continue;
+ UInt8 msgBuffer[String_BufferSize(STRING_SIZE)];
+ String msg = String_InitAndClearArray(msgBuffer);
+
+ String_AppendConst(&msg, "&a");
+ String_AppendString(&msg, &Gfx_ApiInfo[i]);
+ Chat_Add(&msg);
}
}
@@ -208,38 +299,40 @@ void GpuInfoCommand_Make(ChatCommand* cmd) {
String name = String_FromConst("GpuInfo"); cmd->Name = name;
String help0 = String_FromConst("&a/client gpuinfo"); cmd->Help[0] = help0;
String help1 = String_FromConst("&eDisplays information about your GPU."); cmd->Help[1] = help1;
+ cmd->Execute = GpuInfoCommand_Execute;
}
void RenderTypeCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
if (argsCount == 1) {
- game.Chat.Add("&e/client: &cYou didn't specify a new render type.");
- } else if (game.SetRenderType(args[1])) {
- game.Chat.Add("&e/client: &fRender type is now " + args[1] + ".");
+ Chat_AddRaw(tmp, "&e/client: &cYou didn't specify a new render type.");
+ } else if (Game_SetRenderType(&args[1])) {
+ Commands_Log("&e/client: &fRender type is now ", &args[1], ".");
} else {
- game.Chat.Add("&e/client: &cUnrecognised render type &f\"" + args[1] + "\"&c.");
+ Commands_Log("&e/client: &cUnrecognised render type &f\"", &args[1], "\"&c.");
}
}
void RenderTypeCommand_Make(ChatCommand* cmd) {
- String name = String_FromConst("RenderType"); cmd->Name = name;
+ String name = String_FromConst("RenderType"); cmd->Name = name;
String help0 = String_FromConst("&a/client rendertype [normal/legacy/legacyfast]"); cmd->Help[0] = help0;
String help1 = String_FromConst("&bnormal: &eDefault renderer, with all environmental effects enabled."); cmd->Help[1] = help1;
String help2 = String_FromConst("&blegacy: &eMay be slightly slower than normal, but produces the same environmental effects."); cmd->Help[2] = help2;
String help3 = String_FromConst("&blegacyfast: &eSacrifices clouds, fog and overhead sky for faster performance."); cmd->Help[3] = help3;
String help4 = String_FromConst("&bnormalfast: &eSacrifices clouds, fog and overhead sky for faster performance."); cmd->Help[4] = help4;
+ cmd->Execute = RenderTypeCommand_Execute;
}
void ResolutionCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
Int32 width, height;
if (argsCount < 3) {
- game.Chat.Add("&e/client: &cYou didn't specify width and height");
+ Chat_AddRaw(tmp, "&e/client: &cYou didn't specify width and height");
} else if (!Convert_TryParseInt32(&args[1], &width) || !Convert_TryParseInt32(&args[2], &height)) {
- game.Chat.Add("&e/client: &cWidth and height must be integers.");
+ Chat_AddRaw(tmp, "&e/client: &cWidth and height must be integers.");
} else if (width <= 0 || height <= 0) {
- game.Chat.Add("&e/client: &cWidth and height must be above 0.");
+ Chat_AddRaw(tmp, "&e/client: &cWidth and height must be above 0.");
} else {
- game.window.ClientSize = new Size(width, height);
- Options_SetInt32(OPTION_WINDOW_WIDTH, width);
+ Window_SetClientSize(Size2D_Make(width, height));
+ Options_SetInt32(OPTION_WINDOW_WIDTH, width);
Options_SetInt32(OPTION_WINDOW_HEIGHT, height);
}
}
@@ -248,13 +341,18 @@ void ResolutionCommand_Make(ChatCommand* cmd) {
String name = String_FromConst("Resolution"); cmd->Name = name;
String help0 = String_FromConst("&a/client resolution [width] [height]"); cmd->Help[0] = help0;
String help1 = String_FromConst("&ePrecisely sets the size of the rendered window."); cmd->Help[1] = help1;
+ cmd->Execute = ResolutionCommand_Execute;
}
void ModelCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
if (argsCount == 1) {
- game.Chat.Add("&e/client model: &cYou didn't specify a model name.");
+ Chat_AddRaw(tmp, "&e/client model: &cYou didn't specify a model name.");
} else {
- game.LocalPlayer.SetModel(Utils.ToLower(args[1]));
+ UInt8 modelBuffer[String_BufferSize(STRING_SIZE)];
+ String model = String_InitAndClearArray(modelBuffer);
+ String_AppendString(&model, &args[1]);
+ String_MakeLowercase(&model);
+ Entity_SetModel(&LocalPlayer_Instance.Base.Base, &model);
}
}
@@ -264,213 +362,176 @@ void ModelCommand_Make(ChatCommand* cmd) {
String help1 = String_FromConst("&bnames: &echibi, chicken, creeper, human, pig, sheep"); cmd->Help[1] = help1;
String help2 = String_FromConst("&e skeleton, spider, zombie, sitting, "); cmd->Help[2] = help2;
cmd->SingleplayerOnly = true;
+ cmd->Execute = ModelCommand_Execute;
+}
+
+Int32 cuboid_block = -1;
+Vector3I cuboid_mark1, cuboid_mark2;
+bool cuboid_persist = false;
+
+bool CuboidCommand_ParseBlock(STRING_PURE String* args, UInt32 argsCount) {
+ if (argsCount == 1) return true;
+ String yes = String_FromConst("yes");
+ if (String_CaselessEquals(&args[1], &yes)) { cuboid_persist = true; return true; }
+
+ Int32 temp = Block_FindID(&args[1]);
+ BlockID block = 0;
+
+ if (temp != -1) {
+ block = (BlockID)temp;
+ } else {
+ #if USE16_BIT
+ if (!Convert_TryParseUInt16(&args[1], &block)) {
+ #else
+ if (!Convert_TryParseUInt8(&args[1], &block)) {
+ #endif
+ Commands_Log("&eCuboid: &c\"", &args[1], "\" is not a valid block name or id."); return false;
+ }
+ }
+
+ if (block >= BLOCK_CPE_COUNT && !Block_IsCustomDefined(block)) {
+ Commands_Log("&eCuboid: &cThere is no block with id \"", &args[1], "\"."); return false;
+ }
+
+ cuboid_block = block;
+ return true;
+}
+
+void CuboidCommand_DoCuboid(void) {
+ Vector3I min, max;
+ Vector3I_Min(&min, &cuboid_mark1, &cuboid_mark2);
+ Vector3I_Max(&max, &cuboid_mark1, &cuboid_mark2);
+ if (!World_IsValidPos_3I(min) || !World_IsValidPos_3I(max)) return;
+
+ BlockID toPlace = (BlockID)cuboid_block;
+ if (cuboid_block == -1) toPlace = Inventory_SelectedBlock;
+
+ for (Int32 y = min.Y; y <= max.Y; y++) {
+ for (Int32 z = min.Z; z <= max.Z; z++) {
+ for (Int32 x = min.X; x <= max.X; x++) {
+ Game_UpdateBlock(x, y, z, toPlace);
+ }
+ }
+ }
+}
+
+void CuboidCommand_BlockChanged(void* obj, Vector3I coords, BlockID oldBlock, BlockID block) {
+ if (cuboid_mark1.X == Int32_MaxValue) {
+ cuboid_mark1 = coords;
+ Game_UpdateBlock(coords.X, coords.Y, coords.Z, oldBlock);
+ UInt8 msgBuffer[String_BufferSize(STRING_SIZE)];
+ String msg = String_InitAndClearArray(msgBuffer);
+
+ String_AppendConst(&msg, "&eCuboid: &fMark 1 placed at (");
+ String_AppendInt32(&msg, coords.X); String_AppendConst(&msg, ", ");
+ String_AppendInt32(&msg, coords.Y); String_AppendConst(&msg, ", ");
+ String_AppendInt32(&msg, coords.Z);
+ String_AppendConst(&msg, "), place mark 2.");
+ Chat_AddOf(&msg, MESSAGE_TYPE_CLIENTSTATUS_3);
+ } else {
+ cuboid_mark2 = coords;
+ CuboidCommand_DoCuboid();
+ String empty = String_MakeNull(); Chat_AddOf(&empty, MESSAGE_TYPE_CLIENTSTATUS_3);
+
+ if (!cuboid_persist) {
+ Event_UnregisterBlock(&UserEvents_BlockChanged, NULL, CuboidCommand_BlockChanged);
+ } else {
+ cuboid_mark1 = Vector3I_Create1(Int32_MaxValue);
+ String msg = String_FromConst("&eCuboid: &fPlace or delete a block.");
+ Chat_AddOf(&msg, MESSAGE_TYPE_CLIENTSTATUS_3);
+ }
+ }
+}
+
+void CuboidCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
+ Event_UnregisterBlock(&UserEvents_BlockChanged, NULL, CuboidCommand_BlockChanged);
+ cuboid_block = -1;
+ cuboid_mark1 = Vector3I_Create1(Int32_MaxValue);
+ cuboid_mark2 = Vector3I_Create1(Int32_MaxValue);
+ cuboid_persist = false;
+
+ if (!CuboidCommand_ParseBlock(args, argsCount)) return;
+ String yes = String_FromConst("yes");
+ if (argsCount > 2 && String_CaselessEquals(&args[2], &yes)) {
+ cuboid_persist = true;
+ }
+
+ String msg = String_FromConst("&eCuboid: &fPlace or delete a block.");
+ Chat_AddOf(&msg, MESSAGE_TYPE_CLIENTSTATUS_3);
+ Event_RegisterBlock(&UserEvents_BlockChanged, NULL, CuboidCommand_BlockChanged);
}
void CuboidCommand_Make(ChatCommand* cmd) {
- String name = String_FromConst("Cuboid");
- Help = new string[]{
- "&a/client cuboid [block] [persist]",
- "&eFills the 3D rectangle between two points with [block].",
- "&eIf no block is given, uses your currently held block.",
- "&e If persist is given and is \"yes\", then the command",
- "&e will repeatedly cuboid, without needing to be typed in again.",
- };
+ String name = String_FromConst("Cuboid"); cmd->Name = name;
+ String help0 = String_FromConst("&a/client cuboid [block] [persist]"); cmd->Help[0] = help0;
+ String help1 = String_FromConst("&eFills the 3D rectangle between two points with [block]."); cmd->Help[1] = help1;
+ String help2 = String_FromConst("&eIf no block is given, uses your currently held block."); cmd->Help[2] = help2;
+ String help3 = String_FromConst("&e If persist is given and is \"yes\", then the command"); cmd->Help[3] = help3;
+ String help4 = String_FromConst("&e will repeatedly cuboid, without needing to be typed in again."); cmd->Help[4] = help4;
cmd->SingleplayerOnly = true;
+ cmd->Execute = CuboidCommand_Execute;
}
- int block = -1;
- Vector3I mark1, mark2;
- bool persist = false;
- void CuboidCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
- game.UserEvents.BlockChanged -= BlockChanged;
- block = -1;
- mark1 = new Vector3I(int.MaxValue);
- mark2 = new Vector3I(int.MaxValue);
- persist = false;
-
- if (!ParseBlock(args)) return;
- if (args.Length > 2 && Utils.CaselessEquals(args[2], "yes"))
- persist = true;
-
- game.Chat.Add("&eCuboid: &fPlace or delete a block.", MessageType.ClientStatus3);
- game.UserEvents.BlockChanged += BlockChanged;
- }
-
- bool ParseBlock(string[] args) {
- if (args.Length == 1) return true;
- if (Utils.CaselessEquals(args[1], "yes")) { persist = true; return true; }
-
- int temp = -1;
- BlockID block = 0;
- if ((temp = BlockInfo.FindID(args[1])) != -1) {
- block = (BlockID)temp;
- }
- else if (!BlockID.TryParse(args[1], out block)) {
- game.Chat.Add("&eCuboid: &c\"" + args[1] + "\" is not a valid block name or id."); return false;
+void TeleportCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
+ if (argsCount != 4) {
+ Chat_AddRaw(tmp, "&e/client teleport: &cYou didn't specify X, Y and Z coordinates.");
+ } else {
+ Real32 x, y, z;
+ if (!Convert_TryParseReal32(&args[1], &x) || !Convert_TryParseReal32(&args[2], &y) || !Convert_TryParseReal32(&args[3], &z)) {
+ Chat_AddRaw(tmp, "&e/client teleport: &cCoordinates must be decimals");
+ return;
}
- if (block >= Block.CpeCount && BlockInfo.Name[block] == "Invalid") {
- game.Chat.Add("&eCuboid: &cThere is no block with id \"" + args[1] + "\"."); return false;
- }
- this.block = block;
- return true;
- }
-
- void BlockChanged(object sender, BlockChangedEventArgs e) {
- if (mark1.X == int.MaxValue) {
- mark1 = e.Coords;
- game.UpdateBlock(mark1.X, mark1.Y, mark1.Z, e.OldBlock);
- game.Chat.Add("&eCuboid: &fMark 1 placed at (" + e.Coords + "), place mark 2.",
- MessageType.ClientStatus3);
- }
- else {
- mark2 = e.Coords;
- DoCuboid();
- game.Chat.Add(null, MessageType.ClientStatus3);
-
- if (!persist) {
- game.UserEvents.BlockChanged -= BlockChanged;
- }
- else {
- mark1 = new Vector3I(int.MaxValue);
- game.Chat.Add("&eCuboid: &fPlace or delete a block.", MessageType.ClientStatus3);
- }
- }
- }
-
- void DoCuboid() {
- Vector3I min = Vector3I.Min(mark1, mark2);
- Vector3I max = Vector3I.Max(mark1, mark2);
- if (!game.World.IsValidPos(min) || !game.World.IsValidPos(max)) return;
-
- BlockID toPlace = (BlockID)block;
- if (block == -1) toPlace = game.Inventory.Selected;
-
- for (int y = min.Y; y <= max.Y; y++)
- for (int z = min.Z; z <= max.Z; z++)
- for (int x = min.X; x <= max.X; x++)
- {
- game.UpdateBlock(x, y, z, toPlace);
- }
+ Vector3 v = VECTOR3_CONST(x, y, z);
+ LocationUpdate update; LocationUpdate_MakePos(&update, v, false);
+ Entity* entity = &LocalPlayer_Instance.Base.Base;
+ entity->VTABLE->SetLocation(entity, &update, false);
}
}
void TeleportCommand_Make(ChatCommand* cmd) {
- String name = String_FromConst("TP"); cmd->Name = name;
+ String name = String_FromConst("TP"); cmd->Name = name;
String help0 = String_FromConst("&a/client tp [x y z]"); cmd->Help[0] = help0;
String help1 = String_FromConst("&eMoves you to the given coordinates."); cmd->Help[1] = help1;
cmd->SingleplayerOnly = true;
+ cmd->Execute = TeleportCommand_Execute;
}
- void TeleportCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
- if (args.Length != 4) {
- game.Chat.Add("&e/client teleport: &cYou didn't specify X, Y and Z coordinates.");
- } else {
- float x = 0, y = 0, z = 0;
- if (!Utils.TryParseDecimal(args[1], out x) ||
- !Utils.TryParseDecimal(args[2], out y) ||
- !Utils.TryParseDecimal(args[3], out z)) {
- game.Chat.Add("&e/client teleport: &cCoordinates must be decimals");
- return;
- }
- Vector3 v = new Vector3(x, y, z);
- LocationUpdate update = LocationUpdate.MakePos(v, false);
- game.LocalPlayer.SetLocation(update, false);
- }
+void Chat_Send(STRING_PURE String* text) {
+ if (text->length == 0) return;
+ StringsBuffer_Add(&InputLog, text);
+
+ if (Commands_IsCommandPrefix(text)) {
+ Commands_Execute(text);
+ } else {
+ ServerConnection_SendChat(text);
}
}
+
+void Commands_Init(void) {
+ Commands_Register(GpuInfoCommand_Make);
+ Commands_Register(HelpCommand_Make);
+ Commands_Register(RenderTypeCommand_Make);
+ Commands_Register(ResolutionCommand_Make);
+ Commands_Register(ModelCommand_Make);
+ Commands_Register(CuboidCommand_Make);
+ Commands_Register(TeleportCommand_Make);
}
-ChatCommand commands_List[10];
-UInt32 commands_Count;
-void Init() {
- Register(new GpuInfoCommand());
- Register(new HelpCommand());
- Register(new RenderTypeCommand());
- Register(new ResolutionCommand());
- Register(new ModelCommand());
- Register(new CuboidCommand());
- Register(new TeleportCommand());
+void Chat_Reset(void) {
+ Chat_CloseLog();
+ String_Clear(&Chat_LogName);
}
-void Register(Command command) {
- RegisteredCommands.Add(command);
+void Commands_Free(void) {
+ commands_count = 0;
}
-ChatCommand* Commands_GetMatch(STRING_PURE String* cmdName) {
- ChatCommand* match = NULL;
- UInt32 i;
- for (i = 0; i < commands_Count; i++) {
- ChatCommand* cmd = &commands_List[i];
- if (!String_CaselessStarts(&cmd->Name, cmdName)) continue;
-
- if (match != NULL) {
- game.Chat.Add("&e/client: Multiple commands found that start with: \"&f" + cmdName + "&e\".");
- return NULL;
- }
- match = cmd;
- }
-
- if (match == NULL) {
- game.Chat.Add("&e/client: Unrecognised command: \"&f" + cmdName + "&e\".");
- game.Chat.Add("&e/client: Type &a/client &efor a list of commands.");
- return NULL;
- }
- if (match->SingleplayerOnly && !ServerConnection_IsSinglePlayer) {
- game.Chat.Add("&e/client: \"&f" + cmdName + "&e\" can only be used in singleplayer.");
- return NULL;
- }
- return match;
-}
-
-void Commands_Execute(STRING_PURE String* input) {
- String text = *input;
- String prefix = String_FromConst(COMMANDS_PREFIX);
-
- if (String_CaselessStarts(&text, &prefix)) { /* /client command args */
- text = String_UNSAFE_SubstringAt(&text, prefix.length);
- text = text.TrimStart(splitChar);
- } else { /* /command args */
- text = String_UNSAFE_SubstringAt(&text, 1);
- }
-
- if (text.length == 0) { /* only / or /client */
- String m1 = String_FromConst("&eList of client commands:"); Chat_Add(&m1);
- Commands_PrintDefined();
- String m2 = String_FromConst("&eTo see help for a command, type &a/client help [cmd name]"); Chat_Add(&m2);
- return;
- }
-
- String args[10];
- UInt32 argsCount = Array_NumElements(args);
- String_UNSAFE_Split(&text, ' ', args, &argsCount);
-
- ChatCommand* cmd = Commands_GetMatch(&args[0]);
- if (cmd == NULL) return;
- cmd->Execute(args, argsCount);
-}
-
-void Commands_PrintDefined(void) {
- UInt8 strBuffer[String_BufferSize(STRING_SIZE)];
- String str = String_InitAndClearArray(strBuffer);
- UInt32 i;
-
- for (i = 0; i < commands_Count; i++) {
- ChatCommand* cmd = &commands_List[i];
- String name = cmd->Name;
-
- if ((str.length + name.length + 2) > str.capacity) {
- Chat_Add(&str);
- String_Clear(&str);
- }
- String_Append(&str, &name);
- String_AppendConst(&str, ", ");
- }
-
- if (str.length > 0) { Chat_Add(&str); }
-}
-
-void Dispose() {
- RegisteredCommands.Clear();
+IGameComponent Chat_MakeGameComponent(void) {
+ IGameComponent comp = IGameComponent_MakeEmpty();
+ comp.Init = Commands_Init;
+ comp.Reset = Chat_Reset;
+ comp.Free = Commands_Free;
+ return comp;
}
\ No newline at end of file
diff --git a/src/Client/Chat.h b/src/Client/Chat.h
index 347d783d5..804af7c77 100644
--- a/src/Client/Chat.h
+++ b/src/Client/Chat.h
@@ -17,5 +17,5 @@ IGameComponent Chat_MakeGameComponent(void);
void Chat_SetLogName(STRING_PURE String* name);
void Chat_Send(STRING_PURE String* text);
void Chat_Add(STRING_PURE String* text);
-void Chat_AddOf(STRING_PURE String* text, MessageType type);
+void Chat_AddOf(STRING_PURE String* text, Int32 messageType);
#endif
\ No newline at end of file
diff --git a/src/Client/GraphicsAPI.h b/src/Client/GraphicsAPI.h
index f042331d6..01d45f622 100644
--- a/src/Client/GraphicsAPI.h
+++ b/src/Client/GraphicsAPI.h
@@ -111,6 +111,5 @@ void Gfx_SetVSync(bool value);
void Gfx_OnWindowResize(void);
void Gfx_MakeApiInfo(void);
-#define Gfx_ApiInfo_Count 8
-String Gfx_ApiInfo[Gfx_ApiInfo_Count];
+String Gfx_ApiInfo[8];
#endif
\ No newline at end of file
diff --git a/src/Client/Gui.c b/src/Client/Gui.c
index b68521e08..abe6d4131 100644
--- a/src/Client/Gui.c
+++ b/src/Client/Gui.c
@@ -79,11 +79,11 @@ void Gui_FileChanged(void* obj, Stream* stream) {
String guiClassic = String_FromConst("gui_classic.png");
String icons = String_FromConst("icons.png");
- if (String_Equals(&stream->Name, &gui)) {
+ if (String_CaselessEquals(&stream->Name, &gui)) {
Game_UpdateTexture(&Gui_GuiTex, stream, false);
- } else if (String_Equals(&stream->Name, &guiClassic)) {
+ } else if (String_CaselessEquals(&stream->Name, &guiClassic)) {
Game_UpdateTexture(&Gui_GuiClassicTex, stream, false);
- } else if (String_Equals(&stream->Name, &icons)) {
+ } else if (String_CaselessEquals(&stream->Name, &icons)) {
Game_UpdateTexture(&Gui_IconsTex, stream, false);
}
}
diff --git a/src/Client/ModelCache.c b/src/Client/ModelCache.c
index 8dfcd5c25..ac926dc54 100644
--- a/src/Client/ModelCache.c
+++ b/src/Client/ModelCache.c
@@ -8,8 +8,7 @@
#include "TerrainAtlas.h"
#include "Drawer.h"
-String ModelCache_charPngString = String_FromConst("char.png");
-Int32 ModelCache_texCount, ModelCache_modelCount;
+UInt32 ModelCache_texCount, ModelCache_modelCount;
void ModelCache_ContextLost(void* obj) {
Gfx_DeleteVb(&ModelCache_Vb);
@@ -20,7 +19,7 @@ void ModelCache_ContextRecreated(void* obj) {
}
IModel* ModelCache_Get(STRING_PURE String* name) {
- Int32 i;
+ UInt32 i;
for (i = 0; i < ModelCache_modelCount; i++) {
CachedModel* m = &ModelCache_Models[i];
if (!String_CaselessEquals(&m->Name, name)) continue;
@@ -35,7 +34,7 @@ IModel* ModelCache_Get(STRING_PURE String* name) {
}
Int32 ModelCache_GetTextureIndex(STRING_PURE String* texName) {
- Int32 i;
+ UInt32 i;
for (i = 0; i < ModelCache_texCount; i++) {
CachedTexture* tex = &ModelCache_Textures[i];
if (String_CaselessEquals(&tex->Name, texName)) return i;
@@ -48,8 +47,7 @@ void ModelCache_Register(STRING_REF const UInt8* name, STRING_PURE const UInt8*
CachedModel model;
model.Name = String_FromReadonly(name);
model.Instance = instance;
- ModelCache_Models[ModelCache_modelCount] = model;
- ModelCache_modelCount++;
+ ModelCache_Models[ModelCache_modelCount++] = model;
if (defaultTexName != NULL) {
String defaultTex = String_FromReadonly(defaultTexName);
@@ -65,21 +63,20 @@ void ModelCache_RegisterTexture(STRING_REF const UInt8* texName) {
CachedTexture tex;
tex.Name = String_FromReadonly(texName);
tex.TexID = NULL;
- ModelCache_Textures[ModelCache_texCount] = tex;
- ModelCache_texCount++;
+ ModelCache_Textures[ModelCache_texCount++] = tex;
} else {
ErrorHandler_Fail("ModelCache_RegisterTexture - hit max textures");
}
}
-
-static void ModelCache_TextureChanged(void* obj, Stream* stream) {
- Int32 i;
+void ModelCache_TextureChanged(void* obj, Stream* stream) {
+ UInt32 i;
+ String charPng = String_FromConst("char.png");
for (i = 0; i < ModelCache_texCount; i++) {
CachedTexture* tex = &ModelCache_Textures[i];
- if (!String_Equals(&tex->Name, &stream->Name)) continue;
+ if (!String_CaselessEquals(&tex->Name, &stream->Name)) continue;
- bool isCharPng = String_Equals(&stream->Name, &ModelCache_charPngString);
+ bool isCharPng = String_CaselessEquals(&stream->Name, &charPng);
Game_UpdateTexture(&tex->TexID, stream, isCharPng);
return;
}
@@ -166,7 +163,7 @@ void ChickenModel_DrawModel(Entity* entity) {
IModel_DrawRotate(0, 0, Math_AbsF(entity->Anim.LeftArmX), Chicken_RightWing, false);
PackedCol col = IModel_Cols[0];
- Int32 i;
+ UInt32 i;
for (i = 0; i < FACE_COUNT; i++) {
IModel_Cols[i] = PackedCol_Scale(col, 0.7f);
}
@@ -1263,7 +1260,7 @@ void BlockModel_DrawModel(Entity* p) {
if (Block_Draw[BlockModel_block] == DRAW_GAS) return;
if (Block_FullBright[BlockModel_block]) {
- Int32 i;
+ UInt32 i;
PackedCol white = PACKEDCOL_WHITE;
for (i = 0; i < FACE_COUNT; i++) {
IModel_Cols[i] = white;
@@ -1335,7 +1332,7 @@ void ModelCache_Init(void) {
}
void ModelCache_Free(void) {
- Int32 i;
+ UInt32 i;
for (i = 0; i < ModelCache_texCount; i++) {
CachedTexture* tex = &ModelCache_Textures[i];
Gfx_DeleteTexture(&tex->TexID);
diff --git a/src/Client/NetworkEnums.h b/src/Client/NetworkEnums.h
index e2cc7f61a..3b7ca94f0 100644
--- a/src/Client/NetworkEnums.h
+++ b/src/Client/NetworkEnums.h
@@ -55,8 +55,7 @@ typedef UInt8 Opcode;
#define Opcode_CPE_SET_INVENTORY_ORDER 44
-/* Chat message types.*/
-typedef UInt8 MessageType;
+/* === Chat message types === */
/* CPE message types */
#define MESSAGE_TYPE_NORMAL 0
diff --git a/src/Client/Particle.c b/src/Client/Particle.c
index 52d4e3b9d..af718bf81 100644
--- a/src/Client/Particle.c
+++ b/src/Client/Particle.c
@@ -172,8 +172,8 @@ Random rnd;
void Particles_FileChanged(void* obj, Stream* stream) {
String particlesPng = String_FromConst("particles.png");
- if (String_Equals(&stream->Name, &particlesPng)) {
- //Game_UpdateTexture(&Particles_TexId, stream, false);
+ if (String_CaselessEquals(&stream->Name, &particlesPng)) {
+ Game_UpdateTexture(&Particles_TexId, stream, false);
}
}
diff --git a/src/Client/Physics.c b/src/Client/Physics.c
index 007601c22..54088b5c3 100644
--- a/src/Client/Physics.c
+++ b/src/Client/Physics.c
@@ -399,7 +399,8 @@ void Physics_PlaceSponge(Int32 index, BlockID block) {
for (yy = y - 2; yy <= y + 2; yy++) {
for (zz = z - 2; zz <= z + 2; zz++) {
for (xx = x - 2; xx <= x + 2; xx++) {
- block = World_SafeGetBlock(xx, yy, zz);
+ if (!World_IsValidPos(xx, yy, zz)) continue;
+ block = World_GetBlock(xx, yy, zz);
if (block == BLOCK_WATER || block == BLOCK_STILL_WATER) {
Game_UpdateBlock(xx, yy, zz, BLOCK_AIR);
}
diff --git a/src/Client/SkyboxRenderer.c b/src/Client/SkyboxRenderer.c
index 92e8d1130..8d547c112 100644
--- a/src/Client/SkyboxRenderer.c
+++ b/src/Client/SkyboxRenderer.c
@@ -27,9 +27,9 @@ void SkyboxRenderer_FileChanged(void* obj, Stream* src) {
String skybox = String_FromConst("skybox.png");
String useclouds = String_FromConst("useclouds");
- if (String_Equals(&src->Name, &skybox)) {
+ if (String_CaselessEquals(&src->Name, &skybox)) {
Game_UpdateTexture(&skybox_tex, src, false);
- } else if (String_Equals(&src->Name, &useclouds)) {
+ } else if (String_CaselessEquals(&src->Name, &useclouds)) {
WorldEnv_SkyboxClouds = true;
}
}
diff --git a/src/Client/Typedefs.h b/src/Client/Typedefs.h
index f5f1b562f..de6eb34b6 100644
--- a/src/Client/Typedefs.h
+++ b/src/Client/Typedefs.h
@@ -37,7 +37,11 @@ typedef UInt8 bool;
#define false 0
#define NULL 0
+#if USE16_BIT
+typedef UInt16 BlockID;
+#else
typedef UInt8 BlockID;
+#endif
typedef UInt8 EntityID;
typedef UInt8 TextureLoc;
/* Sides of a block. TODO: Map this to CPE PlayerClicked blockface enums. */
diff --git a/src/Client/WeatherRenderer.c b/src/Client/WeatherRenderer.c
index 714e2a8f5..d561b5d19 100644
--- a/src/Client/WeatherRenderer.c
+++ b/src/Client/WeatherRenderer.c
@@ -185,9 +185,9 @@ void WeatherRenderer_FileChanged(void* obj, Stream* stream) {
String snow = String_FromConst("snow.png");
String rain = String_FromConst("rain.png");
- if (String_Equals(&stream->Name, &snow)) {
+ if (String_CaselessEquals(&stream->Name, &snow)) {
Game_UpdateTexture(&weather_snowTex, stream, false);
- } else if (String_Equals(&stream->Name, &rain)) {
+ } else if (String_CaselessEquals(&stream->Name, &rain)) {
Game_UpdateTexture(&weather_rainTex, stream, false);
}
}
diff --git a/src/Client/World.c b/src/Client/World.c
index 2e1278ab0..602d9844d 100644
--- a/src/Client/World.c
+++ b/src/Client/World.c
@@ -49,6 +49,7 @@ void World_SetNewMap(BlockID* blocks, Int32 blocksSize, Int32 width, Int32 heigh
}
}
+
BlockID World_GetPhysicsBlock(Int32 x, Int32 y, Int32 z) {
if (x < 0 || x >= World_Width || z < 0 || z >= World_Length || y < 0) return BLOCK_BEDROCK;
if (y >= World_Height) return BLOCK_AIR;
@@ -56,18 +57,11 @@ BlockID World_GetPhysicsBlock(Int32 x, Int32 y, Int32 z) {
return World_Blocks[World_Pack(x, y, z)];
}
-
-BlockID World_SafeGetBlock(Int32 x, Int32 y, Int32 z) {
- return World_IsValidPos(x, y, z) ?
- World_Blocks[World_Pack(x, y, z)] : BLOCK_AIR;
-}
-
BlockID World_SafeGetBlock_3I(Vector3I p) {
return World_IsValidPos(p.X, p.Y, p.Z) ?
World_Blocks[World_Pack(p.X, p.Y, p.Z)] : BLOCK_AIR;
}
-
bool World_IsValidPos(Int32 x, Int32 y, Int32 z) {
return x >= 0 && y >= 0 && z >= 0 &&
x < World_Width && y < World_Height && z < World_Length;
diff --git a/src/Client/World.h b/src/Client/World.h
index 2b448a775..5ed4cb3f1 100644
--- a/src/Client/World.h
+++ b/src/Client/World.h
@@ -34,7 +34,6 @@ BlockID World_GetPhysicsBlock(Int32 x, Int32 y, Int32 z);
#define World_SetBlock_3I(p, blockId) World_Blocks[World_Pack(p.X, p.Y, p.Z)] = blockId
#define World_GetBlock(x, y, z) World_Blocks[World_Pack(x, y, z)]
#define World_GetBlock_3I(p) World_Blocks[World_Pack(p.X, p.Y, p.Z)]
-BlockID World_SafeGetBlock(Int32 x, Int32 y, Int32 z);
BlockID World_SafeGetBlock_3I(Vector3I p);
bool World_IsValidPos(Int32 x, Int32 y, Int32 z);