mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-19 04:26:52 -04:00
Finish HacksComponent, integrate AutoRotate into Block header
This commit is contained in:
parent
160d1874a6
commit
b181be4af0
@ -157,15 +157,11 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
int a1 = ((p1 & alphaMask) >> 24) & 0xFF;
|
||||
int a2 = ((p2 & alphaMask) >> 24) & 0xFF;
|
||||
int aSum = (a1 + a2);
|
||||
aSum = aSum > 0 ? aSum : 2; // avoid divide by 0 below
|
||||
aSum = aSum > 0 ? aSum : 1; // avoid divide by 0 below
|
||||
|
||||
// Convert RGB to pre-multiplied form
|
||||
int r1 = ((p1 >> 16) & 0xFF) * a1;
|
||||
int r2 = ((p2 >> 16) & 0xFF) * a2;
|
||||
int g1 = ((p1 >> 8) & 0xFF) * a1;
|
||||
int g2 = ((p2 >> 8) & 0xFF) * a2;
|
||||
int b1 = (p1 & 0xFF) * a1;
|
||||
int b2 = (p2 & 0xFF) * a2;
|
||||
int r1 = ((p1 >> 16) & 0xFF) * a1, g1 = ((p1 >> 8) & 0xFF) * a1, b1 = (p1 & 0xFF) * a1;
|
||||
int r2 = ((p2 >> 16) & 0xFF) * a2, g2 = ((p2 >> 8) & 0xFF) * a2, b2 = (p2 & 0xFF) * a2;
|
||||
|
||||
// https://stackoverflow.com/a/347376
|
||||
// We need to convert RGB back from the pre-multiplied average into normal form
|
||||
|
@ -1,121 +0,0 @@
|
||||
#if 0
|
||||
#include "AutoRotate.h"
|
||||
#include "Block.h"
|
||||
#include "GameProps.h"
|
||||
#include "LocationUpdate.h"
|
||||
#include "LocalPlayer.h"
|
||||
#include "Funcs.h"
|
||||
|
||||
#define AR_EQ1(s, x) (s.length >= 1 && Char_ToLower(s.buffer[0]) == x)
|
||||
#define AR_EQ2(s, x, y) (s.length >= 2 && Char_ToLower(s.buffer[0]) == x && Char_ToLower(s.buffer[1]) == y)
|
||||
|
||||
BlockID AutoRotate_RotateBlock(BlockID block) {
|
||||
String name = Block_Name[block];
|
||||
Int32 dirIndex = String_LastIndexOf(&name, '-');
|
||||
if (dirIndex == -1) return block; /* not a directional block */
|
||||
|
||||
String dir = name.Substring(dirIndex + 1);
|
||||
name = name.Substring(0, dirIndex);
|
||||
|
||||
Vector3 translated, offset;
|
||||
Vector3I_ToVector3(&translated, &Game_SelectedPos.TranslatedPos);
|
||||
Vector3_Subtract(&offset, &Game_SelectedPos.Intersect, &translated);
|
||||
|
||||
if (AR_EQ2(dir, 'n','w') || AR_EQ2(dir, 'n','e') || AR_EQ2(dir, 's','w') || AR_EQ2(dir, 's','e')) {
|
||||
return AutoRotate_RotateCorner(block, &name, offset);
|
||||
} else if (AR_EQ1(dir, 'u') || AR_EQ1(dir, 'd')) {
|
||||
return AutoRotate_RotateVertical(block, &name, offset);
|
||||
} else if (AR_EQ1(dir, 'n') || AR_EQ1(dir, 'w') || AR_EQ1(dir, 's') || AR_EQ1(dir, 'e')) {
|
||||
return AutoRotate_RotateDirection(block, &name, offset);
|
||||
} else if (AR_EQ2(dir, 'u','d') || AR_EQ2(dir, 'w','e') || AR_EQ2(dir, 'n','s')) {
|
||||
return AutoRotate_RotateOther(block, &name, offset);
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
BlockID AutoRotate_RotateCorner(BlockID block, String* name, Vector3 offset) {
|
||||
if (offset.X < 0.5f && offset.Z < 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-NW");
|
||||
} else if (offset.X >= 0.5f && offset.Z < 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-NE");
|
||||
} else if (offset.X < 0.5f && offset.Z >= 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-SW");
|
||||
} else if (offset.X >= 0.5f && offset.Z >= 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-SE");
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
BlockID AutoRotate_RotateVertical(BlockID block, String* name, Vector3 offset) {
|
||||
if (offset.Y >= 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-U");
|
||||
} else {
|
||||
return AutoRotate_Find(block, name, "-D");
|
||||
}
|
||||
}
|
||||
|
||||
BlockID AutoRotate_RotateOther(BlockID block, String* name, Vector3 offset) {
|
||||
/* Fence type blocks */
|
||||
if (AutoRotate_Find(BlockID_Invalid, name, "-UD") == BlockID_Invalid) {
|
||||
Real32 headY = LocalPlayer_Instance.Base.Base.HeadY;
|
||||
headY = LocationUpdate_Clamp(headY);
|
||||
|
||||
if (headY < 45.0f || (headY >= 135.0f && headY < 225.0f) || headY > 315.0f) {
|
||||
return AutoRotate_Find(block, name, "-WE");
|
||||
} else {
|
||||
return AutoRotate_Find(block, name, "-NS");
|
||||
}
|
||||
}
|
||||
|
||||
/* Thin pillar type blocks */
|
||||
Face face = Game_SelectedPos.ClosestFace;
|
||||
if (face == Face_YMax || face == Face_YMin)
|
||||
return AutoRotate_Find(block, name, "-UD");
|
||||
if (face == Face_XMax || face == Face_XMin)
|
||||
return AutoRotate_Find(block, name, "-WE");
|
||||
if (face == Face_ZMax || face == Face_ZMin)
|
||||
return AutoRotate_Find(block, name, "-NS");
|
||||
return block;
|
||||
}
|
||||
|
||||
BlockID AutoRotate_RotateDirection(BlockID block, String* name, Vector3 offset) {
|
||||
Vector3 SE = Vector3_Create3(+1.0f, 0.0f, 1.0f);
|
||||
Vector3 SW = Vector3_Create3(-1.0f, 0.0f, 1.0f);
|
||||
|
||||
Vector3I pos = Game_SelectedPos.TranslatedPos;
|
||||
Vector3 exact = Game_SelectedPos.Intersect;
|
||||
Vector3 exactFlat = exact; exactFlat.Y = 0.0f;
|
||||
|
||||
Vector3 SEToPoint = exactFlat; SEToPoint.X -= pos.X; SEToPoint.Z -= pos.Z;
|
||||
Vector3 SWToPoint = exactFlat; SWToPoint.X -= (pos.X + 1); SWToPoint.Z -= pos.Z;
|
||||
|
||||
Real32 dotSE = Vector3_Dot(&SEToPoint, &SW);
|
||||
Real32 dotSW = Vector3_Dot(&SWToPoint, &SE);
|
||||
|
||||
if (dotSE <= 0.0f) { /* NorthEast */
|
||||
if (dotSW <= 0.0f) { /* NorthWest */
|
||||
return AutoRotate_Find(block, name, "-N");
|
||||
} else { /* SouthEast */
|
||||
return AutoRotate_Find(block, name, "-E");
|
||||
}
|
||||
} else { /* SouthWest */
|
||||
if (dotSW <= 0.0f) { /* NorthWest */
|
||||
return AutoRotate_Find(block, name, "-W");
|
||||
} else { /* SouthEast */
|
||||
return AutoRotate_Find(block, name, "-S");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BlockID AutoRotate_Find(BlockID block, String* name, const UInt8* suffix) {
|
||||
UInt8 buffer[String_BufferSize(128)];
|
||||
String temp = String_FromRawBuffer(buffer, 128);
|
||||
String_AppendString(&temp, name);
|
||||
String_AppendConstant(&temp, suffix);
|
||||
|
||||
Int32 rotated = Block_FindID(&temp);
|
||||
if (rotated != -1) return (BlockID)rotated;
|
||||
return block;
|
||||
}
|
||||
#endif
|
@ -1,27 +0,0 @@
|
||||
#if 0
|
||||
#ifndef CS_AUTOROTATE_H
|
||||
#define CS_AUTOROTATE_H
|
||||
#include "Typedefs.h"
|
||||
#include "BlockID.h"
|
||||
#include "String.h"
|
||||
#include "Vectors.h"
|
||||
|
||||
/* Performs automatic rotation of directional blocks.
|
||||
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
/* Attempts to find the rotated block based on the user's orientation and offset on selected block. */
|
||||
BlockID AutoRotate_RotateBlock(BlockID block);
|
||||
|
||||
|
||||
static BlockID AutoRotate_RotateCorner(BlockID block, String* name, Vector3 offset);
|
||||
|
||||
static BlockID AutoRotate_RotateVertical(BlockID block, String* name, Vector3 offset);
|
||||
|
||||
static BlockID AutoRotate_RotateOther(BlockID block, String* name, Vector3 offset);
|
||||
|
||||
static BlockID AutoRotate_RotateDirection(BlockID block, String* name, Vector3 offset);
|
||||
|
||||
static BlockID AutoRotate_Find(BlockID block, String* name, const UInt8* suffix);
|
||||
#endif
|
||||
#endif
|
@ -3,6 +3,22 @@
|
||||
#include "Funcs.h"
|
||||
#include "ExtMath.h"
|
||||
#include "TerrainAtlas.h"
|
||||
#include "Player.h"
|
||||
|
||||
TextureLoc Block_TopTex[Block_CpeCount] = { 0, 1, 0, 2, 16, 4, 15, 17, 14, 14,
|
||||
30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 24, 23, 6, 6, 7, 9, 4,
|
||||
36, 37, 16, 11, 25, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 26, 53, 52, };
|
||||
|
||||
TextureLoc Block_SideTex[Block_CpeCount] = { 0, 1, 3, 2, 16, 4, 15, 17, 14, 14,
|
||||
30, 30, 18, 19, 32, 33, 34, 20, 22, 48, 49, 64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 40, 39, 5, 5, 7, 8, 35,
|
||||
36, 37, 16, 11, 41, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 42, 53, 52, };
|
||||
|
||||
TextureLoc Block_BottomTex[Block_CpeCount] = { 0, 1, 2, 2, 16, 4, 15, 17, 14, 14,
|
||||
30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 56, 55, 6, 6, 7, 10, 4,
|
||||
36, 37, 16, 11, 57, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 58, 53, 52 };
|
||||
|
||||
void Block_Reset(void) {
|
||||
Block_Init();
|
||||
@ -102,9 +118,9 @@ void Block_ResetProps(BlockID block) {
|
||||
Block_SetSide(0, block);
|
||||
#endif
|
||||
} else {
|
||||
Block_SetTex(topTex[block], Face_YMax, block);
|
||||
Block_SetTex(bottomTex[block], Face_YMin, block);
|
||||
Block_SetSide(sideTex[block], block);
|
||||
Block_SetTex(Block_TopTex[block], Face_YMax, block);
|
||||
Block_SetTex(Block_BottomTex[block], Face_YMin, block);
|
||||
Block_SetSide(Block_SideTex[block], block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,4 +439,117 @@ void Block_SetXStretch(BlockID block, bool stretch) {
|
||||
void Block_SetZStretch(BlockID block, bool stretch) {
|
||||
Block_CanStretch[block] &= 0xFC; /* ~0x03 */
|
||||
Block_CanStretch[block] |= (stretch ? 0x03 : (UInt8)0);
|
||||
}
|
||||
|
||||
|
||||
#define AR_EQ1(s, x) (s.length >= 1 && Char_ToLower(s.buffer[0]) == x)
|
||||
#define AR_EQ2(s, x, y) (s.length >= 2 && Char_ToLower(s.buffer[0]) == x && Char_ToLower(s.buffer[1]) == y)
|
||||
|
||||
BlockID AutoRotate_Find(BlockID block, String* name, const UInt8* suffix) {
|
||||
UInt8 buffer[String_BufferSize(128)];
|
||||
String temp = String_FromRawBuffer(buffer, 128);
|
||||
String_AppendString(&temp, name);
|
||||
String_AppendConstant(&temp, suffix);
|
||||
|
||||
Int32 rotated = Block_FindID(&temp);
|
||||
if (rotated != -1) return (BlockID)rotated;
|
||||
return block;
|
||||
}
|
||||
|
||||
BlockID AutoRotate_RotateCorner(BlockID block, String* name, Vector3 offset) {
|
||||
if (offset.X < 0.5f && offset.Z < 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-NW");
|
||||
} else if (offset.X >= 0.5f && offset.Z < 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-NE");
|
||||
} else if (offset.X < 0.5f && offset.Z >= 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-SW");
|
||||
} else if (offset.X >= 0.5f && offset.Z >= 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-SE");
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
BlockID AutoRotate_RotateVertical(BlockID block, String* name, Vector3 offset) {
|
||||
if (offset.Y >= 0.5f) {
|
||||
return AutoRotate_Find(block, name, "-U");
|
||||
} else {
|
||||
return AutoRotate_Find(block, name, "-D");
|
||||
}
|
||||
}
|
||||
|
||||
BlockID AutoRotate_RotateOther(BlockID block, String* name, Vector3 offset) {
|
||||
/* Fence type blocks */
|
||||
if (AutoRotate_Find(BlockID_Invalid, name, "-UD") == BlockID_Invalid) {
|
||||
Real32 headY = LocalPlayer_Instance.Base.Base.HeadY;
|
||||
headY = LocationUpdate_Clamp(headY);
|
||||
|
||||
if (headY < 45.0f || (headY >= 135.0f && headY < 225.0f) || headY > 315.0f) {
|
||||
return AutoRotate_Find(block, name, "-WE");
|
||||
} else {
|
||||
return AutoRotate_Find(block, name, "-NS");
|
||||
}
|
||||
}
|
||||
|
||||
/* Thin pillar type blocks */
|
||||
Face face = Game_SelectedPos.ClosestFace;
|
||||
if (face == Face_YMax || face == Face_YMin)
|
||||
return AutoRotate_Find(block, name, "-UD");
|
||||
if (face == Face_XMax || face == Face_XMin)
|
||||
return AutoRotate_Find(block, name, "-WE");
|
||||
if (face == Face_ZMax || face == Face_ZMin)
|
||||
return AutoRotate_Find(block, name, "-NS");
|
||||
return block;
|
||||
}
|
||||
|
||||
BlockID AutoRotate_RotateDirection(BlockID block, String* name, Vector3 offset) {
|
||||
Vector3 SE = Vector3_Create3(+1.0f, 0.0f, 1.0f);
|
||||
Vector3 SW = Vector3_Create3(-1.0f, 0.0f, 1.0f);
|
||||
|
||||
Vector3I pos = Game_SelectedPos.TranslatedPos;
|
||||
Vector3 exact = Game_SelectedPos.Intersect;
|
||||
Vector3 exactFlat = exact; exactFlat.Y = 0.0f;
|
||||
|
||||
Vector3 SEToPoint = exactFlat; SEToPoint.X -= pos.X; SEToPoint.Z -= pos.Z;
|
||||
Vector3 SWToPoint = exactFlat; SWToPoint.X -= (pos.X + 1); SWToPoint.Z -= pos.Z;
|
||||
|
||||
Real32 dotSE = Vector3_Dot(&SEToPoint, &SW);
|
||||
Real32 dotSW = Vector3_Dot(&SWToPoint, &SE);
|
||||
|
||||
if (dotSE <= 0.0f) { /* NorthEast */
|
||||
if (dotSW <= 0.0f) { /* NorthWest */
|
||||
return AutoRotate_Find(block, name, "-N");
|
||||
} else { /* SouthEast */
|
||||
return AutoRotate_Find(block, name, "-E");
|
||||
}
|
||||
} else { /* SouthWest */
|
||||
if (dotSW <= 0.0f) { /* NorthWest */
|
||||
return AutoRotate_Find(block, name, "-W");
|
||||
} else { /* SouthEast */
|
||||
return AutoRotate_Find(block, name, "-S");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlockID AutoRotate_RotateBlock(BlockID block) {
|
||||
String name = Block_Name[block];
|
||||
Int32 dirIndex = String_LastIndexOf(&name, '-');
|
||||
if (dirIndex == -1) return block; /* not a directional block */
|
||||
|
||||
String dir = String_UNSAFE_SubstringAt(&name, dirIndex + 1);
|
||||
String baseName = String_UNSAFE_Substring(&name, 0, dirIndex);
|
||||
|
||||
Vector3 translated, offset;
|
||||
Vector3I_ToVector3(&translated, &Game_SelectedPos.TranslatedPos);
|
||||
Vector3_Subtract(&offset, &Game_SelectedPos.Intersect, &translated);
|
||||
|
||||
if (AR_EQ2(dir, 'n', 'w') || AR_EQ2(dir, 'n', 'e') || AR_EQ2(dir, 's', 'w') || AR_EQ2(dir, 's', 'e')) {
|
||||
return AutoRotate_RotateCorner(block, &baseName, offset);
|
||||
} else if (AR_EQ1(dir, 'u') || AR_EQ1(dir, 'd')) {
|
||||
return AutoRotate_RotateVertical(block, &baseName, offset);
|
||||
} else if (AR_EQ1(dir, 'n') || AR_EQ1(dir, 'w') || AR_EQ1(dir, 's') || AR_EQ1(dir, 'e')) {
|
||||
return AutoRotate_RotateDirection(block, &baseName, offset);
|
||||
} else if (AR_EQ2(dir, 'u', 'd') || AR_EQ2(dir, 'w', 'e') || AR_EQ2(dir, 'n', 's')) {
|
||||
return AutoRotate_RotateOther(block, &baseName, offset);
|
||||
}
|
||||
return block;
|
||||
}
|
@ -9,7 +9,8 @@
|
||||
#include "Bitmap.h"
|
||||
#include "Constants.h"
|
||||
#include "Compiler.h"
|
||||
/* Stores properties and data for blocks
|
||||
/* Stores properties and data for blocks.
|
||||
Also performs automatic rotation of directional blocks.
|
||||
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
@ -242,20 +243,6 @@ static void Block_SetXStretch(BlockID block, bool stretch);
|
||||
|
||||
static void Block_SetZStretch(BlockID block, bool stretch);
|
||||
|
||||
|
||||
static TextureLoc topTex[Block_CpeCount] = { 0, 1, 0, 2, 16, 4, 15, 17, 14, 14,
|
||||
30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 24, 23, 6, 6, 7, 9, 4,
|
||||
36, 37, 16, 11, 25, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 26, 53, 52, };
|
||||
|
||||
static TextureLoc sideTex[Block_CpeCount] = { 0, 1, 3, 2, 16, 4, 15, 17, 14, 14,
|
||||
30, 30, 18, 19, 32, 33, 34, 20, 22, 48, 49, 64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 40, 39, 5, 5, 7, 8, 35,
|
||||
36, 37, 16, 11, 41, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 42, 53, 52, };
|
||||
|
||||
static TextureLoc bottomTex[Block_CpeCount] = { 0, 1, 2, 2, 16, 4, 15, 17, 14, 14,
|
||||
30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 56, 55, 6, 6, 7, 10, 4,
|
||||
36, 37, 16, 11, 57, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 58, 53, 52 };
|
||||
|
||||
/* Attempts to find the rotated block based on the user's orientation and offset on selected block. */
|
||||
BlockID AutoRotate_RotateBlock(BlockID block);
|
||||
#endif
|
@ -175,7 +175,6 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="2DStructs.h" />
|
||||
<ClInclude Include="AABB.h" />
|
||||
<ClInclude Include="AutoRotate.h" />
|
||||
<ClInclude Include="AxisLinesRenderer.h" />
|
||||
<ClInclude Include="BlockID.h" />
|
||||
<ClInclude Include="Block.h" />
|
||||
@ -249,7 +248,6 @@
|
||||
<ClCompile Include="2DStructs.c" />
|
||||
<ClCompile Include="AABB.c" />
|
||||
<ClCompile Include="EntityComponents.c" />
|
||||
<ClCompile Include="AutoRotate.c" />
|
||||
<ClCompile Include="AxisLinesRenderer.c" />
|
||||
<ClCompile Include="Block.c" />
|
||||
<ClCompile Include="BordersRenderer.c" />
|
||||
|
@ -342,9 +342,6 @@
|
||||
<ClInclude Include="ModelCache.h">
|
||||
<Filter>Header Files\Entities\Model</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AutoRotate.h">
|
||||
<Filter>Header Files\Blocks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DisplayDevice.h">
|
||||
<Filter>Header Files\Platform\Window</Filter>
|
||||
</ClInclude>
|
||||
@ -515,9 +512,6 @@
|
||||
<ClCompile Include="ModelCache.c">
|
||||
<Filter>Source Files\Entities\Model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AutoRotate.c">
|
||||
<Filter>Source Files\Blocks</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TiltComp.c">
|
||||
<Filter>Source Files\Entities\Components</Filter>
|
||||
</ClCompile>
|
||||
|
@ -166,10 +166,10 @@ void HacksComponent_ParseHorizontalSpeed(HacksComponent* hacks) {
|
||||
Int32 end = String_IndexOf(joined, ' ', start);
|
||||
if (end < 0) end = joined->length;
|
||||
|
||||
string num = joined.Substring(start, end - start);
|
||||
Real32 value = 0.0f;
|
||||
if (!Convert_TryParseReal32(num, &value) || value <= 0.0f) return;
|
||||
hacks->MaxSpeedMultiplier = value;
|
||||
String speedStr = String_UNSAFE_Substring(joined, start, end - start);
|
||||
Real32 speed = 0.0f;
|
||||
if (!Convert_TryParseReal32(&speedStr, &speed) || speed <= 0.0f) return;
|
||||
hacks->MaxSpeedMultiplier = speed;
|
||||
}
|
||||
|
||||
void HacksComponent_ParseFlag(HacksComponent* hacks, const UInt8* incFlag, const UInt8* excFlag, bool* target) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "String.h"
|
||||
#include "Funcs.h"
|
||||
#include "ErrorHandler.h"
|
||||
|
||||
String String_FromEmptyBuffer(UInt8* buffer, UInt16 capacity) {
|
||||
String str;
|
||||
@ -54,6 +55,24 @@ void String_Clear(STRING_TRANSIENT String* str) {
|
||||
str->length = 0;
|
||||
}
|
||||
|
||||
String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length) {
|
||||
if (offset < 0 || offset > str->length) {
|
||||
ErrorHandler_Fail("Offset for substring out of range");
|
||||
}
|
||||
if (length < 0 || length > str->length) {
|
||||
ErrorHandler_Fail("Length for substring out of range");
|
||||
}
|
||||
if (offset + length > str->length) {
|
||||
ErrorHandler_Fail("Result substring is out of range");
|
||||
}
|
||||
|
||||
String sub = *str;
|
||||
sub.buffer += offset;
|
||||
sub.length = length;
|
||||
sub.capacity = length;
|
||||
return sub;
|
||||
}
|
||||
|
||||
|
||||
bool String_Equals(STRING_TRANSIENT String* a, STRING_TRANSIENT String* b) {
|
||||
if (a->length != b->length) return false;
|
||||
@ -186,14 +205,6 @@ Int32 String_IndexOfString(STRING_TRANSIENT String* str, STRING_TRANSIENT String
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool String_ContainsString(STRING_TRANSIENT String* str, STRING_TRANSIENT String* sub) {
|
||||
return String_IndexOfString(str, sub) >= 0;
|
||||
}
|
||||
|
||||
bool String_StartsWith(STRING_TRANSIENT String* str, STRING_TRANSIENT String* sub) {
|
||||
return String_IndexOfString(str, sub) == 0;
|
||||
}
|
||||
|
||||
|
||||
#define Convert_ControlCharsCount 32
|
||||
UInt16 Convert_ControlChars[Convert_ControlCharsCount] = {
|
||||
|
@ -35,6 +35,10 @@ String String_MakeNull(void);
|
||||
void String_MakeLowercase(STRING_TRANSIENT String* str);
|
||||
/* Sets all characters in the given string to NULL, then sets length t0 0. */
|
||||
void String_Clear(STRING_TRANSIENT String* str);
|
||||
/* Returns a string that points directly to a substring of the given string.
|
||||
NOTE: THIS IS UNSAFE - IT MAINTAINS A REFERENCE TO THE ORIGINAL BUFFER, AND THE SUBSTRING IS NOT NULL TERMINATED */
|
||||
String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length);
|
||||
#define String_UNSAFE_SubstringAt(str, offset) (String_UNSAFE_Substring(str, offset, (str)->length - (offset)))
|
||||
|
||||
/* Returns whether two strings have same contents. */
|
||||
bool String_Equals(STRING_TRANSIENT String* a, STRING_TRANSIENT String* b);
|
||||
@ -62,9 +66,9 @@ UInt8 String_CharAt(STRING_TRANSIENT String* str, Int32 offset);
|
||||
/* Find the first index of sub in given string, -1 if not found. */
|
||||
Int32 String_IndexOfString(STRING_TRANSIENT String* str, STRING_TRANSIENT String* sub);
|
||||
/* Returns whether sub is contained within string. */
|
||||
bool String_ContainsString(STRING_TRANSIENT String* str, STRING_TRANSIENT String* sub);
|
||||
#define String_ContainsString(str, sub) (String_IndexOfString(str, sub) >= 0)
|
||||
/* Returns whether given string starts with sub. */
|
||||
bool String_StartsWith(STRING_TRANSIENT String* str, STRING_TRANSIENT String* sub);
|
||||
#define String_StartsWith(str, sub) (String_IndexOfString(str, sub) == 0)
|
||||
|
||||
/* Converts a code page 437 index into a unicode character. */
|
||||
UInt16 Convert_CP437ToUnicode(UInt8 c);
|
||||
|
Loading…
x
Reference in New Issue
Block a user