Port Commands to C. (also use caseless equals more often)

This commit is contained in:
UnknownShadow200 2018-03-13 08:04:52 +11:00
parent 0c0072025c
commit 12e274af77
21 changed files with 373 additions and 335 deletions

View File

@ -16,12 +16,12 @@ namespace ClassicalSharp.Commands {
public class CommandList : IGameComponent { public class CommandList : IGameComponent {
const string prefix = "/client"; const string prefix = "/client", prefixSpace = "/client ";
public bool IsCommandPrefix(string input) { public bool IsCommandPrefix(string input) {
if (game.Server.IsSinglePlayer && Utils.CaselessStarts(input, "/")) if (game.Server.IsSinglePlayer && Utils.CaselessStarts(input, "/"))
return true; return true;
return Utils.CaselessStarts(input, prefix + " ") return Utils.CaselessStarts(input, prefixSpace)
|| Utils.CaselessEquals(input, prefix); || Utils.CaselessEquals(input, prefix);
} }
@ -75,8 +75,10 @@ namespace ClassicalSharp.Commands {
static char[] splitChar = { ' ' }; static char[] splitChar = { ' ' };
public void Execute(string text) { public void Execute(string text) {
if (Utils.CaselessStarts(text, prefix)) { // /client command args if (Utils.CaselessStarts(text, prefixSpace)) { // /client command args
text = text.Substring(prefix.Length).TrimStart(splitChar); text = text.Substring(prefixSpace.Length);
} else if (Utils.CaselessStarts(text, prefix)) { // /clientcommand args
text = text.Substring(prefix.Length);
} else { // /command args } else { // /command args
text = text.Substring(1); text = text.Substring(1);
} }

View File

@ -168,15 +168,16 @@ namespace ClassicalSharp.Commands {
if (args.Length == 1) return true; if (args.Length == 1) return true;
if (Utils.CaselessEquals(args[1], "yes")) { persist = true; return true; } if (Utils.CaselessEquals(args[1], "yes")) { persist = true; return true; }
int temp = -1; int temp = BlockInfo.FindID(args[1]);
BlockID block = 0; BlockID block = 0;
if ((temp = BlockInfo.FindID(args[1])) != -1) {
if (temp != -1) {
block = (BlockID)temp; block = (BlockID)temp;
} else if (!BlockID.TryParse(args[1], out block)) { } 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; 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; game.Chat.Add("&eCuboid: &cThere is no block with id \"" + args[1] + "\"."); return false;
} }
this.block = block; this.block = block;

View File

@ -76,13 +76,6 @@ namespace ClassicalSharp.Map {
return blocks[(p.Y * Length + p.Z) * Width + p.X]; return blocks[(p.Y * Length + p.Z) * Width + p.X];
} }
/// <summary> Returns the block at the given world coordinates with bounds checking,
/// returning 0 is the coordinates were outside the map. </summary>
public BlockID SafeGetBlock(int x, int y, int z) {
return IsValidPos(x, y, z) ?
blocks[(y * Length + z) * Width + x] : Block.Air;
}
/// <summary> Returns the block at the given world coordinates with bounds checking, /// <summary> Returns the block at the given world coordinates with bounds checking,
/// returning 0 is the coordinates were outside the map. </summary> /// returning 0 is the coordinates were outside the map. </summary>
public BlockID SafeGetBlock(Vector3I p) { public BlockID SafeGetBlock(Vector3I p) {

View File

@ -26,7 +26,7 @@ namespace ClassicalSharp {
public Vector3I BlockPos; public Vector3I BlockPos;
/// <summary> Integer world coordinates of the neighbouring block that is closest to the player. </summary> /// <summary> Integer world coordinates of the neighbouring block that is closest to the player. </summary>
public Vector3I TranslatedPos { get { return BlockPos + offsets[(byte)Face]; } } public Vector3I TranslatedPos;
/// <summary> Whether this instance actually has a selected block currently. </summary> /// <summary> Whether this instance actually has a selected block currently. </summary>
public bool Valid = true; public bool Valid = true;
@ -41,11 +41,11 @@ namespace ClassicalSharp {
/// calculates the closest face of the selected block's position. </summary> /// calculates the closest face of the selected block's position. </summary>
public void SetAsValid(int x, int y, int z, Vector3 min, Vector3 max, public void SetAsValid(int x, int y, int z, Vector3 min, Vector3 max,
BlockID block, Vector3 intersect) { BlockID block, Vector3 intersect) {
Min = min; Vector3I pos = new Vector3I(x, y, z);
Max = max;
BlockPos = new Vector3I(x, y, z);
Valid = true; Valid = true;
BlockPos = pos;
Block = block; Block = block;
Min = min; Max = max;
Intersect = intersect; Intersect = intersect;
float dist = float.PositiveInfinity; float dist = float.PositiveInfinity;
@ -55,14 +55,25 @@ namespace ClassicalSharp {
TestAxis(intersect.Y - Max.Y, ref dist, BlockFace.YMax); TestAxis(intersect.Y - Max.Y, ref dist, BlockFace.YMax);
TestAxis(intersect.Z - Min.Z, ref dist, BlockFace.ZMin); TestAxis(intersect.Z - Min.Z, ref dist, BlockFace.ZMin);
TestAxis(intersect.Z - Max.Z, ref dist, BlockFace.ZMax); 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;
} }
/// <summary> Mark this as not having a selected block. </summary> /// <summary> Mark this as not having a selected block. </summary>
public void SetAsInvalid() { public void SetAsInvalid() {
Valid = false; Valid = false;
BlockPos = Vector3I.MinusOne; BlockPos = Vector3I.MinusOne;
Face = (BlockFace)6;
Block = 0; Block = 0;
TranslatedPos = Vector3I.MinusOne;
Face = (BlockFace)6;
} }
void TestAxis(float dAxis, ref float dist, BlockFace fAxis) { void TestAxis(float dAxis, ref float dist, BlockFace fAxis) {
@ -70,11 +81,5 @@ namespace ClassicalSharp {
if (dAxis >= dist) return; if (dAxis >= dist) return;
dist = dAxis; Face = fAxis; dist = dAxis; Face = fAxis;
} }
static Vector3I[] offsets = new Vector3I[] {
Vector3I.UnitX, -Vector3I.UnitX, Vector3I.UnitY,
-Vector3I.UnitY, Vector3I.UnitZ, -Vector3I.UnitZ,
Vector3I.Zero,
};
} }
} }

View File

@ -151,22 +151,22 @@ namespace ClassicalSharp.Network.Protocols {
void HandleMakeSelection() { void HandleMakeSelection() {
byte selectionId = reader.ReadUInt8(); byte selectionId = reader.ReadUInt8();
string label = reader.ReadString(); string label = reader.ReadString();
Vector3I start, end;
start.X = reader.ReadInt16(); Vector3I p1;
start.Y = reader.ReadInt16(); p1.X = reader.ReadInt16();
start.Z = reader.ReadInt16(); p1.Y = reader.ReadInt16();
p1.Z = reader.ReadInt16();
end.X = reader.ReadInt16(); Vector3I p2;
end.Y = reader.ReadInt16(); p2.X = reader.ReadInt16();
end.Z = reader.ReadInt16(); p2.Y = reader.ReadInt16();
p2.Z = reader.ReadInt16();
byte r = (byte)reader.ReadInt16(); byte r = (byte)reader.ReadInt16();
byte g = (byte)reader.ReadInt16(); byte g = (byte)reader.ReadInt16();
byte b = (byte)reader.ReadInt16(); byte b = (byte)reader.ReadInt16();
byte a = (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); FastColour col = new FastColour(r, g, b, a);
game.SelectionManager.AddSelection(selectionId, p1, p2, col); game.SelectionManager.AddSelection(selectionId, p1, p2, col);
} }

View File

@ -13,9 +13,9 @@ namespace ClassicalSharp.Selections {
public FastColour Colour; public FastColour Colour;
public float MinDist, MaxDist; public float MinDist, MaxDist;
public SelectionBox(Vector3I start, Vector3I end, FastColour col) { public SelectionBox(Vector3I p1, Vector3I p2, FastColour col) {
Min = Vector3I.Min(start, end); Min = Vector3I.Min(p1, p2);
Max = Vector3I.Max(start, end); Max = Vector3I.Max(p1, p2);
Colour = col; Colour = col;
} }

View File

@ -163,9 +163,12 @@ namespace ClassicalSharp.Singleplayer {
for (int zz = z - 2; zz <= z + 2; zz++) for (int zz = z - 2; zz <= z + 2; zz++)
for (int xx = x - 2; xx <= x + 2; xx++) for (int xx = x - 2; xx <= x + 2; xx++)
{ {
block = map.SafeGetBlock(xx, yy, zz); if (!map.IsValidPos(xx, yy, zz)) continue;
if (block == Block.Water || block == Block.StillWater)
block = map.blocks[xx + width * (zz + yy * length)];
if (block == Block.Water || block == Block.StillWater) {
game.UpdateBlock(xx, yy, zz, Block.Air); game.UpdateBlock(xx, yy, zz, Block.Air);
}
} }
} }
@ -184,8 +187,9 @@ namespace ClassicalSharp.Singleplayer {
index = xx + width * (zz + yy * length); index = xx + width * (zz + yy * length);
block = map.blocks[index]; block = map.blocks[index];
if (block == Block.Water || block == Block.StillWater) if (block == Block.Water || block == Block.StillWater) {
Water.Enqueue((1u << tickShift) | (uint)index); Water.Enqueue((1u << tickShift) | (uint)index);
}
} }
} }
} }

View File

@ -6,11 +6,6 @@ namespace ClassicalSharp {
/// <summary> Represents a 3D integer vector. </summary> /// <summary> Represents a 3D integer vector. </summary>
public struct Vector3I { 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 static Vector3I MinusOne = new Vector3I(-1, -1, -1);
public int X, Y, Z; public int X, Y, Z;
@ -23,22 +18,6 @@ namespace ClassicalSharp {
X = value; Y = value; Z = value; 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) { public static explicit operator Vector3(Vector3I value) {
return new Vector3(value.X, value.Y, value.Z); return new Vector3(value.X, value.Y, value.Z);
} }

View File

@ -5,6 +5,12 @@
#include "Game.h" #include "Game.h"
#include "ErrorHandler.h" #include "ErrorHandler.h"
#include "ServerConnection.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) { void ChatLine_Make(ChatLine* line, STRING_TRANSIENT String* text) {
String dst = String_InitAndClearArray(line->Buffer); String dst = String_InitAndClearArray(line->Buffer);
@ -17,17 +23,6 @@ String Chat_LogName = String_FromEmptyArray(Chat_LogNameBuffer);
Stream Chat_LogStream; Stream Chat_LogStream;
DateTime ChatLog_LastLogDate; 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) { void Chat_CloseLog(void) {
if (Chat_LogStream.Data == NULL) return; if (Chat_LogStream.Data == NULL) return;
ReturnCode code = Chat_LogStream.Close(&Chat_LogStream); 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_Add(STRING_PURE String* text) { Chat_AddOf(text, MESSAGE_TYPE_NORMAL); }
void Chat_AddOf(STRING_PURE String* text, MessageType type) { void Chat_AddOf(STRING_PURE String* text, Int32 msgType) {
if (type == MESSAGE_TYPE_NORMAL) { if (msgType == MESSAGE_TYPE_NORMAL) {
StringsBuffer_Add(&ChatLog, text); StringsBuffer_Add(&ChatLog, text);
Chat_AppendLog(text); Chat_AppendLog(text);
} else if (type >= MESSAGE_TYPE_STATUS_1 && type <= MESSAGE_TYPE_STATUS_3) { } else if (msgType >= MESSAGE_TYPE_STATUS_1 && msgType <= MESSAGE_TYPE_STATUS_3) {
ChatLine_Make(&Chat_Status[type - MESSAGE_TYPE_STATUS_1], text); ChatLine_Make(&Chat_Status[msgType - MESSAGE_TYPE_STATUS_1], text);
} else if (type >= MESSAGE_TYPE_BOTTOMRIGHT_1 && type <= MESSAGE_TYPE_BOTTOMRIGHT_3) { } else if (msgType >= MESSAGE_TYPE_BOTTOMRIGHT_1 && msgType <= MESSAGE_TYPE_BOTTOMRIGHT_3) {
ChatLine_Make(&Chat_BottomRight[type - MESSAGE_TYPE_BOTTOMRIGHT_1], text); ChatLine_Make(&Chat_BottomRight[msgType - MESSAGE_TYPE_BOTTOMRIGHT_1], text);
} else if (type == MESSAGE_TYPE_ANNOUNCEMENT) { } else if (msgType == MESSAGE_TYPE_ANNOUNCEMENT) {
ChatLine_Make(&Chat_Announcement, text); ChatLine_Make(&Chat_Announcement, text);
} else if (type >= MESSAGE_TYPE_CLIENTSTATUS_1 && type <= MESSAGE_TYPE_CLIENTSTATUS_3) { } else if (msgType >= MESSAGE_TYPE_CLIENTSTATUS_1 && msgType <= MESSAGE_TYPE_CLIENTSTATUS_3) {
ChatLine_Make(&Chat_ClientStatus[type - MESSAGE_TYPE_CLIENTSTATUS_1], text); 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_ { typedef struct ChatCommand_ {
String Name; String Name;
@ -159,24 +144,124 @@ typedef struct ChatCommand_ {
typedef void (*ChatCommandConstructor)(ChatCommand* cmd); typedef void (*ChatCommandConstructor)(ChatCommand* cmd);
#define COMMANDS_PREFIX "/client" #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) { bool Commands_IsCommandPrefix(STRING_PURE String* input) {
if (input->length == 0) return false; if (input->length == 0) return false;
if (ServerConnection_IsSinglePlayer && input->buffer[0] == '/') if (ServerConnection_IsSinglePlayer && input->buffer[0] == '/')
return true; return true;
String starts = String_FromConst(COMMANDS_PREFIX_STARTS); String prefixSpace = String_FromConst(COMMANDS_PREFIX_SPACE);
String prefix = String_FromConst(COMMANDS_PREFIX); String prefix = String_FromConst(COMMANDS_PREFIX);
return String_CaselessStarts(input, &starts) return String_CaselessStarts(input, &prefixSpace)
|| String_CaselessEquals(input, &prefix); || 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) { void HelpCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
if (argsCount == 1) { if (argsCount == 1) {
game.Chat.Add("&eList of client commands:"); Chat_AddRaw(tmp1, "&eList of client commands:");
Commands_PrintDefined(); 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 { } else {
ChatCommand* cmd = Commands_GetMatch(&args[1]); ChatCommand* cmd = Commands_GetMatch(&args[1]);
if (cmd == NULL) return; if (cmd == NULL) return;
@ -198,9 +283,15 @@ void HelpCommand_Make(ChatCommand* cmd) {
} }
void GpuInfoCommand_Execute(STRING_PURE String* args, UInt32 argsCount) { void GpuInfoCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
string[] lines = game.Graphics.ApiInfo; UInt32 i;
for (int i = 0; i < lines.Length; i++) { for (i = 0; i < Array_NumElements(Gfx_ApiInfo); i++) {
game.Chat.Add("&a" + lines[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 name = String_FromConst("GpuInfo"); cmd->Name = name;
String help0 = String_FromConst("&a/client gpuinfo"); cmd->Help[0] = help0; String help0 = String_FromConst("&a/client gpuinfo"); cmd->Help[0] = help0;
String help1 = String_FromConst("&eDisplays information about your GPU."); cmd->Help[1] = help1; 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) { void RenderTypeCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
if (argsCount == 1) { if (argsCount == 1) {
game.Chat.Add("&e/client: &cYou didn't specify a new render type."); Chat_AddRaw(tmp, "&e/client: &cYou didn't specify a new render type.");
} else if (game.SetRenderType(args[1])) { } else if (Game_SetRenderType(&args[1])) {
game.Chat.Add("&e/client: &fRender type is now " + args[1] + "."); Commands_Log("&e/client: &fRender type is now ", &args[1], ".");
} else { } 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) { 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 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 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 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 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; 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) { void ResolutionCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
Int32 width, height; Int32 width, height;
if (argsCount < 3) { 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)) { } 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) { } 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 { } else {
game.window.ClientSize = new Size(width, height); Window_SetClientSize(Size2D_Make(width, height));
Options_SetInt32(OPTION_WINDOW_WIDTH, width); Options_SetInt32(OPTION_WINDOW_WIDTH, width);
Options_SetInt32(OPTION_WINDOW_HEIGHT, height); Options_SetInt32(OPTION_WINDOW_HEIGHT, height);
} }
} }
@ -248,13 +341,18 @@ void ResolutionCommand_Make(ChatCommand* cmd) {
String name = String_FromConst("Resolution"); cmd->Name = name; String name = String_FromConst("Resolution"); cmd->Name = name;
String help0 = String_FromConst("&a/client resolution [width] [height]"); cmd->Help[0] = help0; 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; 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) { void ModelCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
if (argsCount == 1) { 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 { } 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 help1 = String_FromConst("&bnames: &echibi, chicken, creeper, human, pig, sheep"); cmd->Help[1] = help1;
String help2 = String_FromConst("&e skeleton, spider, zombie, sitting, <numerical block id>"); cmd->Help[2] = help2; String help2 = String_FromConst("&e skeleton, spider, zombie, sitting, <numerical block id>"); cmd->Help[2] = help2;
cmd->SingleplayerOnly = true; 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) { void CuboidCommand_Make(ChatCommand* cmd) {
String name = String_FromConst("Cuboid"); String name = String_FromConst("Cuboid"); cmd->Name = name;
Help = new string[]{ String help0 = String_FromConst("&a/client cuboid [block] [persist]"); cmd->Help[0] = help0;
"&a/client cuboid [block] [persist]", String help1 = String_FromConst("&eFills the 3D rectangle between two points with [block]."); cmd->Help[1] = help1;
"&eFills the 3D rectangle between two points with [block].", String help2 = String_FromConst("&eIf no block is given, uses your currently held block."); cmd->Help[2] = help2;
"&eIf no block is given, uses your currently held block.", String help3 = String_FromConst("&e If persist is given and is \"yes\", then the command"); cmd->Help[3] = help3;
"&e If persist is given and is \"yes\", then the command", String help4 = String_FromConst("&e will repeatedly cuboid, without needing to be typed in again."); cmd->Help[4] = help4;
"&e will repeatedly cuboid, without needing to be typed in again.",
};
cmd->SingleplayerOnly = true; 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) { void TeleportCommand_Execute(STRING_PURE String* args, UInt32 argsCount) {
game.UserEvents.BlockChanged -= BlockChanged; if (argsCount != 4) {
block = -1; Chat_AddRaw(tmp, "&e/client teleport: &cYou didn't specify X, Y and Z coordinates.");
mark1 = new Vector3I(int.MaxValue); } else {
mark2 = new Vector3I(int.MaxValue); Real32 x, y, z;
persist = false; 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");
if (!ParseBlock(args)) return; 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;
} }
if (block >= Block.CpeCount && BlockInfo.Name[block] == "Invalid") { Vector3 v = VECTOR3_CONST(x, y, z);
game.Chat.Add("&eCuboid: &cThere is no block with id \"" + args[1] + "\"."); return false; LocationUpdate update; LocationUpdate_MakePos(&update, v, false);
} Entity* entity = &LocalPlayer_Instance.Base.Base;
this.block = block; entity->VTABLE->SetLocation(entity, &update, false);
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);
}
} }
} }
void TeleportCommand_Make(ChatCommand* cmd) { 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 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; String help1 = String_FromConst("&eMoves you to the given coordinates."); cmd->Help[1] = help1;
cmd->SingleplayerOnly = true; 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); void Chat_Send(STRING_PURE String* text) {
LocationUpdate update = LocationUpdate.MakePos(v, false); if (text->length == 0) return;
game.LocalPlayer.SetLocation(update, false); 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]; void Chat_Reset(void) {
UInt32 commands_Count; Chat_CloseLog();
void Init() { String_Clear(&Chat_LogName);
Register(new GpuInfoCommand());
Register(new HelpCommand());
Register(new RenderTypeCommand());
Register(new ResolutionCommand());
Register(new ModelCommand());
Register(new CuboidCommand());
Register(new TeleportCommand());
} }
void Register(Command command) { void Commands_Free(void) {
RegisteredCommands.Add(command); commands_count = 0;
} }
ChatCommand* Commands_GetMatch(STRING_PURE String* cmdName) { IGameComponent Chat_MakeGameComponent(void) {
ChatCommand* match = NULL; IGameComponent comp = IGameComponent_MakeEmpty();
UInt32 i; comp.Init = Commands_Init;
for (i = 0; i < commands_Count; i++) { comp.Reset = Chat_Reset;
ChatCommand* cmd = &commands_List[i]; comp.Free = Commands_Free;
if (!String_CaselessStarts(&cmd->Name, cmdName)) continue; return comp;
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();
} }

View File

@ -17,5 +17,5 @@ IGameComponent Chat_MakeGameComponent(void);
void Chat_SetLogName(STRING_PURE String* name); void Chat_SetLogName(STRING_PURE String* name);
void Chat_Send(STRING_PURE String* text); void Chat_Send(STRING_PURE String* text);
void Chat_Add(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 #endif

View File

@ -111,6 +111,5 @@ void Gfx_SetVSync(bool value);
void Gfx_OnWindowResize(void); void Gfx_OnWindowResize(void);
void Gfx_MakeApiInfo(void); void Gfx_MakeApiInfo(void);
#define Gfx_ApiInfo_Count 8 String Gfx_ApiInfo[8];
String Gfx_ApiInfo[Gfx_ApiInfo_Count];
#endif #endif

View File

@ -79,11 +79,11 @@ void Gui_FileChanged(void* obj, Stream* stream) {
String guiClassic = String_FromConst("gui_classic.png"); String guiClassic = String_FromConst("gui_classic.png");
String icons = String_FromConst("icons.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); 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); 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); Game_UpdateTexture(&Gui_IconsTex, stream, false);
} }
} }

View File

@ -8,8 +8,7 @@
#include "TerrainAtlas.h" #include "TerrainAtlas.h"
#include "Drawer.h" #include "Drawer.h"
String ModelCache_charPngString = String_FromConst("char.png"); UInt32 ModelCache_texCount, ModelCache_modelCount;
Int32 ModelCache_texCount, ModelCache_modelCount;
void ModelCache_ContextLost(void* obj) { void ModelCache_ContextLost(void* obj) {
Gfx_DeleteVb(&ModelCache_Vb); Gfx_DeleteVb(&ModelCache_Vb);
@ -20,7 +19,7 @@ void ModelCache_ContextRecreated(void* obj) {
} }
IModel* ModelCache_Get(STRING_PURE String* name) { IModel* ModelCache_Get(STRING_PURE String* name) {
Int32 i; UInt32 i;
for (i = 0; i < ModelCache_modelCount; i++) { for (i = 0; i < ModelCache_modelCount; i++) {
CachedModel* m = &ModelCache_Models[i]; CachedModel* m = &ModelCache_Models[i];
if (!String_CaselessEquals(&m->Name, name)) continue; 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 ModelCache_GetTextureIndex(STRING_PURE String* texName) {
Int32 i; UInt32 i;
for (i = 0; i < ModelCache_texCount; i++) { for (i = 0; i < ModelCache_texCount; i++) {
CachedTexture* tex = &ModelCache_Textures[i]; CachedTexture* tex = &ModelCache_Textures[i];
if (String_CaselessEquals(&tex->Name, texName)) return 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; CachedModel model;
model.Name = String_FromReadonly(name); model.Name = String_FromReadonly(name);
model.Instance = instance; model.Instance = instance;
ModelCache_Models[ModelCache_modelCount] = model; ModelCache_Models[ModelCache_modelCount++] = model;
ModelCache_modelCount++;
if (defaultTexName != NULL) { if (defaultTexName != NULL) {
String defaultTex = String_FromReadonly(defaultTexName); String defaultTex = String_FromReadonly(defaultTexName);
@ -65,21 +63,20 @@ void ModelCache_RegisterTexture(STRING_REF const UInt8* texName) {
CachedTexture tex; CachedTexture tex;
tex.Name = String_FromReadonly(texName); tex.Name = String_FromReadonly(texName);
tex.TexID = NULL; tex.TexID = NULL;
ModelCache_Textures[ModelCache_texCount] = tex; ModelCache_Textures[ModelCache_texCount++] = tex;
ModelCache_texCount++;
} else { } else {
ErrorHandler_Fail("ModelCache_RegisterTexture - hit max textures"); ErrorHandler_Fail("ModelCache_RegisterTexture - hit max textures");
} }
} }
void ModelCache_TextureChanged(void* obj, Stream* stream) {
static void ModelCache_TextureChanged(void* obj, Stream* stream) { UInt32 i;
Int32 i; String charPng = String_FromConst("char.png");
for (i = 0; i < ModelCache_texCount; i++) { for (i = 0; i < ModelCache_texCount; i++) {
CachedTexture* tex = &ModelCache_Textures[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); Game_UpdateTexture(&tex->TexID, stream, isCharPng);
return; return;
} }
@ -166,7 +163,7 @@ void ChickenModel_DrawModel(Entity* entity) {
IModel_DrawRotate(0, 0, Math_AbsF(entity->Anim.LeftArmX), Chicken_RightWing, false); IModel_DrawRotate(0, 0, Math_AbsF(entity->Anim.LeftArmX), Chicken_RightWing, false);
PackedCol col = IModel_Cols[0]; PackedCol col = IModel_Cols[0];
Int32 i; UInt32 i;
for (i = 0; i < FACE_COUNT; i++) { for (i = 0; i < FACE_COUNT; i++) {
IModel_Cols[i] = PackedCol_Scale(col, 0.7f); 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_Draw[BlockModel_block] == DRAW_GAS) return;
if (Block_FullBright[BlockModel_block]) { if (Block_FullBright[BlockModel_block]) {
Int32 i; UInt32 i;
PackedCol white = PACKEDCOL_WHITE; PackedCol white = PACKEDCOL_WHITE;
for (i = 0; i < FACE_COUNT; i++) { for (i = 0; i < FACE_COUNT; i++) {
IModel_Cols[i] = white; IModel_Cols[i] = white;
@ -1335,7 +1332,7 @@ void ModelCache_Init(void) {
} }
void ModelCache_Free(void) { void ModelCache_Free(void) {
Int32 i; UInt32 i;
for (i = 0; i < ModelCache_texCount; i++) { for (i = 0; i < ModelCache_texCount; i++) {
CachedTexture* tex = &ModelCache_Textures[i]; CachedTexture* tex = &ModelCache_Textures[i];
Gfx_DeleteTexture(&tex->TexID); Gfx_DeleteTexture(&tex->TexID);

View File

@ -55,8 +55,7 @@ typedef UInt8 Opcode;
#define Opcode_CPE_SET_INVENTORY_ORDER 44 #define Opcode_CPE_SET_INVENTORY_ORDER 44
/* Chat message types.*/ /* === Chat message types === */
typedef UInt8 MessageType;
/* CPE message types */ /* CPE message types */
#define MESSAGE_TYPE_NORMAL 0 #define MESSAGE_TYPE_NORMAL 0

View File

@ -172,8 +172,8 @@ Random rnd;
void Particles_FileChanged(void* obj, Stream* stream) { void Particles_FileChanged(void* obj, Stream* stream) {
String particlesPng = String_FromConst("particles.png"); String particlesPng = String_FromConst("particles.png");
if (String_Equals(&stream->Name, &particlesPng)) { if (String_CaselessEquals(&stream->Name, &particlesPng)) {
//Game_UpdateTexture(&Particles_TexId, stream, false); Game_UpdateTexture(&Particles_TexId, stream, false);
} }
} }

View File

@ -399,7 +399,8 @@ void Physics_PlaceSponge(Int32 index, BlockID block) {
for (yy = y - 2; yy <= y + 2; yy++) { for (yy = y - 2; yy <= y + 2; yy++) {
for (zz = z - 2; zz <= z + 2; zz++) { for (zz = z - 2; zz <= z + 2; zz++) {
for (xx = x - 2; xx <= x + 2; xx++) { 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) { if (block == BLOCK_WATER || block == BLOCK_STILL_WATER) {
Game_UpdateBlock(xx, yy, zz, BLOCK_AIR); Game_UpdateBlock(xx, yy, zz, BLOCK_AIR);
} }

View File

@ -27,9 +27,9 @@ void SkyboxRenderer_FileChanged(void* obj, Stream* src) {
String skybox = String_FromConst("skybox.png"); String skybox = String_FromConst("skybox.png");
String useclouds = String_FromConst("useclouds"); String useclouds = String_FromConst("useclouds");
if (String_Equals(&src->Name, &skybox)) { if (String_CaselessEquals(&src->Name, &skybox)) {
Game_UpdateTexture(&skybox_tex, src, false); Game_UpdateTexture(&skybox_tex, src, false);
} else if (String_Equals(&src->Name, &useclouds)) { } else if (String_CaselessEquals(&src->Name, &useclouds)) {
WorldEnv_SkyboxClouds = true; WorldEnv_SkyboxClouds = true;
} }
} }

View File

@ -37,7 +37,11 @@ typedef UInt8 bool;
#define false 0 #define false 0
#define NULL 0 #define NULL 0
#if USE16_BIT
typedef UInt16 BlockID;
#else
typedef UInt8 BlockID; typedef UInt8 BlockID;
#endif
typedef UInt8 EntityID; typedef UInt8 EntityID;
typedef UInt8 TextureLoc; typedef UInt8 TextureLoc;
/* Sides of a block. TODO: Map this to CPE PlayerClicked blockface enums. */ /* Sides of a block. TODO: Map this to CPE PlayerClicked blockface enums. */

View File

@ -185,9 +185,9 @@ void WeatherRenderer_FileChanged(void* obj, Stream* stream) {
String snow = String_FromConst("snow.png"); String snow = String_FromConst("snow.png");
String rain = String_FromConst("rain.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); 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); Game_UpdateTexture(&weather_rainTex, stream, false);
} }
} }

View File

@ -49,6 +49,7 @@ void World_SetNewMap(BlockID* blocks, Int32 blocksSize, Int32 width, Int32 heigh
} }
} }
BlockID World_GetPhysicsBlock(Int32 x, Int32 y, Int32 z) { 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 (x < 0 || x >= World_Width || z < 0 || z >= World_Length || y < 0) return BLOCK_BEDROCK;
if (y >= World_Height) return BLOCK_AIR; 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)]; 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) { BlockID World_SafeGetBlock_3I(Vector3I p) {
return World_IsValidPos(p.X, p.Y, p.Z) ? return World_IsValidPos(p.X, p.Y, p.Z) ?
World_Blocks[World_Pack(p.X, p.Y, p.Z)] : BLOCK_AIR; World_Blocks[World_Pack(p.X, p.Y, p.Z)] : BLOCK_AIR;
} }
bool World_IsValidPos(Int32 x, Int32 y, Int32 z) { bool World_IsValidPos(Int32 x, Int32 y, Int32 z) {
return x >= 0 && y >= 0 && z >= 0 && return x >= 0 && y >= 0 && z >= 0 &&
x < World_Width && y < World_Height && z < World_Length; x < World_Width && y < World_Height && z < World_Length;

View File

@ -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_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(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)] #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); BlockID World_SafeGetBlock_3I(Vector3I p);
bool World_IsValidPos(Int32 x, Int32 y, Int32 z); bool World_IsValidPos(Int32 x, Int32 y, Int32 z);