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);