More work on porting EntityList to C, split up Entity.c into Entity.c and EntityComponent.c

This commit is contained in:
UnknownShadow200 2017-12-04 16:20:16 +11:00
parent 3bed91af85
commit db7d148a44
19 changed files with 784 additions and 778 deletions

View File

@ -72,8 +72,9 @@ namespace ClassicalSharp.Entities {
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
if (i != closestId || i == SelfID)
if (i != closestId || i == SelfID) {
List[i].RenderName();
}
}
gfx.Texturing = false;
@ -92,8 +93,9 @@ namespace ClassicalSharp.Entities {
&& game.LocalPlayer.Hacks.CanSeeAllNames;
for (int i = 0; i < List.Length; i++) {
bool hover = (i == closestId || allNames) && i != SelfID;
if (List[i] != null && hover)
if (List[i] != null && hover) {
List[i].RenderName();
}
}
gfx.Texturing = false;
@ -176,21 +178,18 @@ namespace ClassicalSharp.Entities {
gfx.SetBatchFormat(VertexFormat.P3fT2fC4b);
ShadowComponent.Draw(game, List[SelfID]);
if (ShadowMode == EntityShadow.CircleAll)
DrawOtherShadows();
if (ShadowMode == EntityShadow.CircleAll) {
for (int i = 0; i < SelfID; i++) {
if (List[i] == null) continue;
Player p = List[i] as Player;
if (p != null) ShadowComponent.Draw(game, p);
}
}
gfx.AlphaArgBlend = false;
gfx.DepthWrite = true;
gfx.AlphaBlending = false;
gfx.Texturing = false;
}
void DrawOtherShadows() {
for (int i = 0; i < SelfID; i++) {
if (List[i] == null) continue;
Player p = List[i] as Player;
if (p != null) ShadowComponent.Draw(game, p);
}
}
}
}

View File

@ -195,6 +195,7 @@
<ClInclude Include="Drawer.h" />
<ClInclude Include="Drawer2D.h" />
<ClInclude Include="Entity.h" />
<ClInclude Include="EntityComponents.h" />
<ClInclude Include="EnvRenderer.h" />
<ClInclude Include="ErrorHandler.h" />
<ClInclude Include="Event.h" />
@ -270,6 +271,7 @@
<ClCompile Include="DisplayDevice.c" />
<ClCompile Include="Drawer.c" />
<ClCompile Include="Drawer2D.c" />
<ClCompile Include="EntityComponents.c" />
<ClCompile Include="EnvRenderer.c" />
<ClCompile Include="Event.c" />
<ClCompile Include="ExtMath.c" />

View File

@ -378,6 +378,9 @@
<ClInclude Include="Hotkeys.h">
<Filter>Header Files\Game</Filter>
</ClInclude>
<ClInclude Include="EntityComponents.h">
<Filter>Header Files\Entities</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Noise.c">
@ -587,5 +590,8 @@
<ClCompile Include="Hotkeys.c">
<Filter>Source Files\Game</Filter>
</ClCompile>
<ClCompile Include="EntityComponents.c">
<Filter>Source Files\Entities</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -352,7 +352,7 @@ void Gfx_SetFogEnd(Real32 value) {
}
D3DFOGMODE d3d9_fogTableMode = D3DFOG_NONE;
void Gfx_SetFogMode(Fog fogMode) {
void Gfx_SetFogMode(Int32 fogMode) {
D3DFOGMODE mode = d3d9_modes[fogMode];
if (mode == d3d9_fogTableMode) return;
@ -376,7 +376,7 @@ void Gfx_SetAlphaTest(bool enabled) {
D3DCMPFUNC d3d9_alphaTestFunc = 0;
Int32 d3d9_alphaTestRef = 0;
void Gfx_SetAlphaTestFunc(CompareFunc compareFunc, Real32 refValue) {
void Gfx_SetAlphaTestFunc(Int32 compareFunc, Real32 refValue) {
d3d9_alphaTestFunc = d3d9_compareFuncs[compareFunc];
D3D9_SetRenderState(d3d9_alphaTestFunc, D3DRS_ALPHAFUNC, "D3D9_SetAlphaTest_Func");
d3d9_alphaTestRef = (Int32)(refValue * 255);
@ -393,7 +393,7 @@ void Gfx_SetAlphaBlending(bool enabled) {
D3DBLEND d3d9_srcBlendFunc = 0;
D3DBLEND d3d9_dstBlendFunc = 0;
void Gfx_SetAlphaBlendFunc(BlendFunc srcBlendFunc, BlendFunc dstBlendFunc) {
void Gfx_SetAlphaBlendFunc(Int32 srcBlendFunc, Int32 dstBlendFunc) {
d3d9_srcBlendFunc = d3d9_blendFuncs[srcBlendFunc];
D3D9_SetRenderState(d3d9_srcBlendFunc, D3DRS_SRCBLEND, "D3D9_SetAlphaBlendFunc_Src");
d3d9_dstBlendFunc = d3d9_blendFuncs[dstBlendFunc];
@ -425,7 +425,7 @@ void Gfx_SetDepthTest(bool enabled) {
}
D3DCMPFUNC d3d9_depthTestFunc = 0;
void Gfx_SetDepthTestFunc(CompareFunc compareFunc) {
void Gfx_SetDepthTestFunc(Int32 compareFunc) {
d3d9_depthTestFunc = d3d9_compareFuncs[compareFunc];
D3D9_SetRenderState(d3d9_alphaTestFunc, D3DRS_ZFUNC, "D3D9_SetDepthTestFunc");
}
@ -442,7 +442,7 @@ void Gfx_SetDepthWrite(bool enabled) {
}
GfxResourceID Gfx_CreateDynamicVb(VertexFormat vertexFormat, Int32 maxVertices) {
GfxResourceID Gfx_CreateDynamicVb(Int32 vertexFormat, Int32 maxVertices) {
Int32 size = maxVertices * Gfx_strideSizes[vertexFormat];
IDirect3DVertexBuffer9* vbuffer;
ReturnCode hresult = IDirect3DDevice9_CreateVertexBuffer(device, size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
@ -462,7 +462,7 @@ void D3D9_SetVbData(IDirect3DVertexBuffer9* buffer, void* data, Int32 size, cons
ErrorHandler_CheckOrFail(hresult, unlockMsg);
}
GfxResourceID Gfx_CreateVb(void* vertices, VertexFormat vertexFormat, Int32 count) {
GfxResourceID Gfx_CreateVb(void* vertices, Int32 vertexFormat, Int32 count) {
Int32 size = count * Gfx_strideSizes[vertexFormat];
IDirect3DVertexBuffer9* vbuffer;
ReturnCode hresult = IDirect3DDevice9_CreateVertexBuffer(device, size, D3DUSAGE_WRITEONLY,
@ -510,8 +510,8 @@ void Gfx_BindIb(GfxResourceID ib) {
void Gfx_DeleteVb(GfxResourceID* vb) { D3D9_FreeResource(vb); }
void Gfx_DeleteIb(GfxResourceID* ib) { D3D9_FreeResource(ib); }
VertexFormat d3d9_batchFormat = -1;
void Gfx_SetBatchFormat(VertexFormat format) {
Int32 d3d9_batchFormat = -1;
void Gfx_SetBatchFormat(Int32 format) {
if (format == d3d9_batchFormat) return;
d3d9_batchFormat = format;
@ -553,7 +553,7 @@ void Gfx_DrawIndexedVb_TrisT2fC4b(Int32 verticesCount, Int32 startVertex) {
}
void Gfx_SetMatrixMode(MatrixType matrixType) {
void Gfx_SetMatrixMode(Int32 matrixType) {
if (matrixType == MATRIX_TYPE_PROJECTION) {
curStack = &projStack;
} else if (matrixType == MATRIX_TYPE_MODELVIEW) {

View File

@ -9,6 +9,8 @@
#include "Platform.h"
#include "Funcs.h"
#include "ModelCache.h"
#include "GraphicsAPI.h"
#include "Intersection.h"
Real32 LocationUpdate_Clamp(Real32 degrees) {
degrees = Math_Mod(degrees, 360.0f);
@ -195,604 +197,176 @@ bool Entity_TouchesAnyWater(Entity* entity) {
}
#define ANIM_MAX_ANGLE (110 * MATH_DEG2RAD)
#define ANIM_ARM_MAX (60.0f * MATH_DEG2RAD)
#define ANIM_LEG_MAX (80.0f * MATH_DEG2RAD)
#define ANIM_IDLE_MAX (3.0f * MATH_DEG2RAD)
#define ANIM_IDLE_XPERIOD (2.0f * MATH_PI / 5.0f)
#define ANIM_IDLE_ZPERIOD (2.0f * MATH_PI / 3.5f)
void AnimatedComp_DoTilt(Real32* tilt, bool reduce) {
if (reduce) {
(*tilt) *= 0.84f;
} else {
(*tilt) += 0.1f;
}
Math_Clamp(*tilt, 0.0f, 1.0f);
}
void AnimatedComp_PerpendicularAnim(AnimatedComp* anim, Real32 flapSpeed, Real32 idleXRot, Real32 idleZRot, bool left) {
Real32 verAngle = 0.5f + 0.5f * Math_Sin(anim->WalkTime * flapSpeed);
Real32 zRot = -idleZRot - verAngle * anim->Swing * ANIM_MAX_ANGLE;
Real32 horAngle = Math_Cos(anim->WalkTime) * anim->Swing * ANIM_ARM_MAX * 1.5f;
Real32 xRot = idleXRot + horAngle;
if (left) {
anim->LeftArmX = xRot; anim->LeftArmZ = zRot;
} else {
anim->RightArmX = xRot; anim->RightArmZ = zRot;
EntityID closestId;
void Entities_Tick(ScheduledTask* task) {
UInt32 i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (Entities_List[i] == NULL) continue;
Entities_List[i]->Tick(Entities_List[i], task);
}
}
void AnimatedComp_CalcHumanAnim(AnimatedComp* anim, Real32 idleXRot, Real32 idleZRot) {
AnimatedComp_PerpendicularAnim(anim, 0.23f, idleXRot, idleZRot, true);
AnimatedComp_PerpendicularAnim(anim, 0.28f, idleXRot, idleZRot, false);
anim->RightArmX = -anim->RightArmX; anim->RightArmZ = -anim->RightArmZ;
}
void AnimatedComp_Init(AnimatedComp* anim) {
anim->BobbingHor = 0.0f; anim->BobbingVer = 0.0f; anim->BobbingModel = 0.0f;
anim->WalkTime = 0.0f; anim->Swing = 0.0f; anim->BobStrength = 1.0f;
anim->WalkTimeO = 0.0f; anim->SwingO = 0.0f; anim->BobStrengthO = 1.0f;
anim->WalkTimeN = 0.0f; anim->SwingN = 0.0f; anim->BobStrengthN = 1.0f;
anim->LeftLegX = 0.0f; anim->LeftLegZ = 0.0f; anim->RightLegX = 0.0f; anim->RightLegZ = 0.0f;
anim->LeftArmX = 0.0f; anim->LeftArmZ = 0.0f; anim->RightArmX = 0.0f; anim->RightArmZ = 0.0f;
}
void AnimatedComp_Update(AnimatedComp* anim, Vector3 oldPos, Vector3 newPos, Real64 delta, bool onGround) {
anim->WalkTimeO = anim->WalkTimeN;
anim->SwingO = anim->SwingN;
Real32 dx = newPos.X - oldPos.X;
Real32 dz = newPos.Z - oldPos.Z;
Real32 distance = Math_Sqrt(dx * dx + dz * dz);
if (distance > 0.05f) {
Real32 walkDelta = distance * 2 * (Real32)(20 * delta);
anim->WalkTimeN += walkDelta;
anim->SwingN += (Real32)delta * 3;
} else {
anim->SwingN -= (Real32)delta * 3;
}
Math_Clamp(anim->SwingN, 0.0f, 1.0f);
/* TODO: the Tilt code was designed for 60 ticks/second, fix it up for 20 ticks/second */
anim->BobStrengthO = anim->BobStrengthN;
Int32 i;
for (i = 0; i < 3; i++) {
AnimatedComp_DoTilt(&anim->BobStrengthN, !Game_ViewBobbing || !onGround);
void Entities_RenderModels(Real64 delta, Real32 t) {
Gfx_SetTexturing(true);
Gfx_SetAlphaTest(true);
UInt32 i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (Entities_List[i] == NULL) continue;
Entities_List[i]->RenderModel(Entities_List[i], delta, t);
}
Gfx_SetTexturing(false);
Gfx_SetAlphaTest(false);
}
void AnimatedComp_GetCurrent(AnimatedComp* anim, Real32 t, bool calcHumanAnims) {
anim->Swing = Math_Lerp(anim->SwingO, anim->SwingN, t);
anim->WalkTime = Math_Lerp(anim->WalkTimeO, anim->WalkTimeN, t);
anim->BobStrength = Math_Lerp(anim->BobStrengthO, anim->BobStrengthN, t);
Real32 idleTime = (Real32)Game_Accumulator;
Real32 idleXRot = Math_Sin(idleTime * ANIM_IDLE_XPERIOD) * ANIM_IDLE_MAX;
Real32 idleZRot = ANIM_IDLE_MAX + Math_Cos(idleTime * ANIM_IDLE_ZPERIOD) * ANIM_IDLE_MAX;
anim->LeftArmX = (Math_Cos(anim->WalkTime) * anim->Swing * ANIM_ARM_MAX) - idleXRot;
anim->LeftArmZ = -idleZRot;
anim->LeftLegX = -(Math_Cos(anim->WalkTime) * anim->Swing * ANIM_LEG_MAX);
anim->LeftLegZ = 0;
anim->RightLegX = -anim->LeftLegX; anim->RightLegZ = -anim->LeftLegZ;
anim->RightArmX = -anim->LeftArmX; anim->RightArmZ = -anim->LeftArmZ;
anim->BobbingHor = Math_Cos(anim->WalkTime) * anim->Swing * (2.5f / 16.0f);
anim->BobbingVer = Math_AbsF(Math_Sin(anim->WalkTime)) * anim->Swing * (2.5f / 16.0f);
anim->BobbingModel = Math_AbsF(Math_Cos(anim->WalkTime)) * anim->Swing * (4.0f / 16.0f);
if (calcHumanAnims && !Game_SimpleArmsAnim) {
AnimatedComp_CalcHumanAnim(anim, idleXRot, idleZRot);
}
}
void TiltComp_Init(TiltComp* anim) {
anim->TiltX = 0.0f; anim->TiltY = 0.0f; anim->VelTiltStrength = 1.0f;
anim->VelTiltStrengthO = 1.0f; anim->VelTiltStrengthN = 1.0f;
}
void TiltComp_Update(TiltComp* anim, Real64 delta) {
anim->VelTiltStrengthO = anim->VelTiltStrengthN;
void Entities_RenderNames(Real64 delta) {
LocalPlayer* p = &LocalPlayer_Instance;
closestId = Entities_GetCloset(&p->Base.Base);
if (!p->Hacks.CanSeeAllNames || Entities_NameMode != NAME_MODE_ALL) return;
/* TODO: the Tilt code was designed for 60 ticks/second, fix it up for 20 ticks/second */
Int32 i;
for (i = 0; i < 3; i++) {
AnimatedComp_DoTilt(&anim->VelTiltStrengthN, p->Hacks.Noclip || p->Hacks.Flying);
Gfx_SetTexturing(true);
Gfx_SetAlphaTest(true);
bool hadFog = Gfx_GetFog();
if (hadFog) Gfx_SetFog(false);
UInt32 i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (Entities_List[i] == NULL) continue;
if (i != closestId || i == ENTITIES_SELF_ID) {
Entities_List[i]->RenderName(Entities_List[i]);
}
}
Gfx_SetTexturing(false);
Gfx_SetAlphaTest(false);
if (hadFog) Gfx_SetFog(true);
}
void TiltComp_GetCurrent(TiltComp* anim, Real32 t) {
void Entities_RenderHoveredNames(Real64 delta) {
LocalPlayer* p = &LocalPlayer_Instance;
anim->VelTiltStrength = Math_Lerp(anim->VelTiltStrengthO, anim->VelTiltStrengthN, t);
bool allNames = !(Entities_NameMode == NAME_MODE_HOVERED || Entities_NameMode == NAME_MODE_ALL)
&& p->Hacks.CanSeeAllNames;
AnimatedComp* pAnim = &p->Base.Base.Anim;
anim->TiltX = Math_Cos(pAnim->WalkTime) * pAnim->Swing * (0.15f * MATH_DEG2RAD);
anim->TiltY = Math_Sin(pAnim->WalkTime) * pAnim->Swing * (0.15f * MATH_DEG2RAD);
}
Gfx_SetTexturing(true);
Gfx_SetAlphaTest(true);
Gfx_SetDepthTest(false);
bool hadFog = Gfx_GetFog();
if (hadFog) Gfx_SetFog(false);
void HacksComp_SetAll(HacksComp* hacks, bool allowed) {
hacks->CanAnyHacks = allowed; hacks->CanFly = allowed;
hacks->CanNoclip = allowed; hacks->CanRespawn = allowed;
hacks->CanSpeed = allowed; hacks->CanPushbackBlocks = allowed;
hacks->CanUseThirdPersonCamera = allowed;
}
void HacksComp_Init(HacksComp* hacks) {
Platform_MemSet(hacks, 0, sizeof(HacksComp));
HacksComp_SetAll(hacks, true);
hacks->SpeedMultiplier = 10.0f;
hacks->Enabled = true;
hacks->CanSeeAllNames = true;
hacks->CanDoubleJump = true;
hacks->BaseHorSpeed = 1.0f;
hacks->MaxJumps = 1;
hacks->NoclipSlide = true;
hacks->CanBePushed = true;
hacks->HacksFlags = String_InitAndClear(&hacks->HacksFlagsBuffer[0], 128);
}
bool HacksComp_CanJumpHigher(HacksComp* hacks) {
return hacks->Enabled && hacks->CanAnyHacks && hacks->CanSpeed;
}
bool HacksComp_Floating(HacksComp* hacks) {
return hacks->Noclip || hacks->Flying;
}
String HacksComp_GetFlagValue(String* flag, HacksComp* hacks) {
String* joined = &hacks->HacksFlags;
Int32 start = String_IndexOfString(joined, flag);
if (start < 0) return String_MakeNull();
start += flag->length;
Int32 end = String_IndexOf(joined, ' ', start);
if (end < 0) end = joined->length;
return String_UNSAFE_Substring(joined, start, end - start);
}
void HacksComp_ParseHorizontalSpeed(HacksComp* hacks) {
String horSpeedFlag = String_FromConst("horspeed=");
String speedStr = HacksComp_GetFlagValue(&horSpeedFlag, hacks);
if (speedStr.length == 0) return;
Real32 speed = 0.0f;
if (!Convert_TryParseReal32(&speedStr, &speed) || speed <= 0.0f) return;
hacks->BaseHorSpeed = speed;
}
void HacksComp_ParseMultiSpeed(HacksComp* hacks) {
String jumpsFlag = String_FromConst("jumps=");
String jumpsStr = HacksComp_GetFlagValue(&jumpsFlag, hacks);
if (jumpsStr.length == 0) return;
Int32 jumps = 0;
if (!Convert_TryParseInt32(&jumpsStr, &jumps) || jumps < 0) return;
hacks->MaxJumps = jumps;
}
void HacksComp_ParseFlag(HacksComp* hacks, const UInt8* incFlag, const UInt8* excFlag, bool* target) {
String include = String_FromReadonly(incFlag);
String exclude = String_FromReadonly(excFlag);
String* joined = &hacks->HacksFlags;
if (String_ContainsString(joined, &include)) {
*target = true;
} else if (String_ContainsString(joined, &exclude)) {
*target = false;
}
}
void HacksComp_ParseAllFlag(HacksComp* hacks, const UInt8* incFlag, const UInt8* excFlag) {
String include = String_FromReadonly(incFlag);
String exclude = String_FromReadonly(excFlag);
String* joined = &hacks->HacksFlags;
if (String_ContainsString(joined, &include)) {
HacksComp_SetAll(hacks, true);
} else if (String_ContainsString(joined, &exclude)) {
HacksComp_SetAll(hacks, false);
}
}
void HacksComp_SetUserType(HacksComp* hacks, UInt8 value) {
bool isOp = value >= 100 && value <= 127;
hacks->UserType = value;
hacks->CanSeeAllNames = isOp;
Block_CanPlace[BLOCK_BEDROCK] = isOp;
Block_CanDelete[BLOCK_BEDROCK] = isOp;
Block_CanPlace[BLOCK_WATER] = isOp;
Block_CanPlace[BLOCK_STILL_WATER] = isOp;
Block_CanPlace[BLOCK_LAVA] = isOp;
Block_CanPlace[BLOCK_STILL_LAVA] = isOp;
}
void HacksComp_CheckConsistency(HacksComp* hacks) {
if (!hacks->CanFly || !hacks->Enabled) {
hacks->Flying = false; hacks->FlyingDown = false; hacks->FlyingUp = false;
}
if (!hacks->CanNoclip || !hacks->Enabled) {
hacks->Noclip = false;
}
if (!hacks->CanSpeed || !hacks->Enabled) {
hacks->Speeding = false; hacks->HalfSpeeding = false;
}
hacks->CanDoubleJump = hacks->CanAnyHacks && hacks->Enabled && hacks->CanSpeed;
hacks->CanSeeAllNames = hacks->CanAnyHacks && hacks->CanSeeAllNames;
if (!hacks->CanUseThirdPersonCamera || !hacks->Enabled) {
Camera_CycleActive();
}
}
void HacksComp_UpdateState(HacksComp* hacks) {
HacksComp_SetAll(hacks, true);
if (hacks->HacksFlags.length == 0) return;
hacks->BaseHorSpeed = 1;
hacks->MaxJumps = 1;
hacks->CanBePushed = true;
/* By default (this is also the case with WoM), we can use hacks. */
String excHacks = String_FromConst("-hax");
if (String_ContainsString(&hacks->HacksFlags, &excHacks)) {
HacksComp_SetAll(hacks, false);
}
HacksComp_ParseFlag(hacks, "+fly", "-fly", &hacks->CanFly);
HacksComp_ParseFlag(hacks, "+noclip", "-noclip", &hacks->CanNoclip);
HacksComp_ParseFlag(hacks, "+speed", "-speed", &hacks->CanSpeed);
HacksComp_ParseFlag(hacks, "+respawn", "-respawn", &hacks->CanRespawn);
HacksComp_ParseFlag(hacks, "+push", "-push", &hacks->CanBePushed);
if (hacks->UserType == 0x64) {
HacksComp_ParseAllFlag(hacks, "+ophax", "-ophax");
}
HacksComp_ParseHorizontalSpeed(hacks);
HacksComp_ParseMultiSpeed(hacks);
HacksComp_CheckConsistency(hacks);
Event_RaiseVoid(&UserEvents_HackPermissionsChanged);
}
void InterpComp_RemoveOldestRotY(InterpComp* interp) {
Int32 i;
for (i = 0; i < Array_NumElements(interp->RotYStates); i++) {
interp->RotYStates[i] = interp->RotYStates[i + 1];
}
interp->RotYCount--;
}
void InterpComp_AddRotY(InterpComp* interp, Real32 state) {
if (interp->RotYCount == Array_NumElements(interp->RotYStates)) {
InterpComp_RemoveOldestRotY(interp);
}
interp->RotYStates[interp->RotYCount] = state; interp->RotYCount++;
}
void InterpComp_AdvanceRotY(InterpComp* interp) {
interp->PrevRotY = interp->NextRotY;
if (interp->RotYCount == 0) return;
interp->NextRotY = interp->RotYStates[0];
InterpComp_RemoveOldestRotY(interp);
}
void InterpComp_LerpAngles(InterpComp* interp, Entity* entity, Real32 t) {
InterpState* prev = &interp->Prev;
InterpState* next = &interp->Next;
entity->HeadX = Math_LerpAngle(prev->HeadX, next->HeadX, t);
entity->HeadY = Math_LerpAngle(prev->HeadY, next->HeadY, t);
entity->RotX = Math_LerpAngle(prev->RotX, next->RotX, t);
entity->RotY = Math_LerpAngle(interp->PrevRotY, interp->NextRotY, t);
entity->RotZ = Math_LerpAngle(prev->RotZ, next->RotZ, t);
}
void InterpComp_SetPos(InterpState* state, LocationUpdate* update) {
if (update->RelativePosition) {
Vector3_Add(&state->Pos, &state->Pos, &update->Pos);
} else {
state->Pos = update->Pos;
}
}
Real32 NetInterpComp_Next(Real32 next, Real32 cur) {
if (next == LOCATIONUPDATE_EXCLUDED) return cur;
return next;
}
void NetInterpComp_RemoveOldestState(NetInterpComp* interp) {
Int32 i;
for (i = 0; i < Array_NumElements(interp->States); i++) {
interp->States[i] = interp->States[i + 1];
}
interp->StatesCount--;
}
void NetInterpComp_AddState(NetInterpComp* interp, InterpState state) {
if (interp->StatesCount == Array_NumElements(interp->States)) {
NetInterpComp_RemoveOldestState(interp);
}
interp->States[interp->StatesCount] = state; interp->StatesCount++;
}
void NetInterpComp_SetLocation(NetInterpComp* interp, LocationUpdate* update, bool interpolate) {
InterpState last = interp->Cur;
InterpState* cur = &interp->Cur;
if (update->IncludesPosition) {
InterpComp_SetPos(cur, update);
}
cur->RotX = NetInterpComp_Next(update->RotX, cur->RotX);
cur->RotZ = NetInterpComp_Next(update->RotZ, cur->RotZ);
cur->HeadX = NetInterpComp_Next(update->HeadX, cur->HeadX);
cur->HeadY = NetInterpComp_Next(update->RotY, cur->HeadY);
if (!interpolate) {
interp->Base.Prev = *cur; interp->Base.PrevRotY = cur->HeadY;
interp->Base.Next = *cur; interp->Base.NextRotY = cur->HeadY;
interp->Base.RotYCount = 0; interp->StatesCount = 0;
} else {
/* Smoother interpolation by also adding midpoint. */
InterpState mid;
Vector3_Lerp(&mid.Pos, &last.Pos, &cur->Pos, 0.5f);
mid.RotX = Math_LerpAngle(last.RotX, cur->RotX, 0.5f);
mid.RotZ = Math_LerpAngle(last.RotZ, cur->RotZ, 0.5f);
mid.HeadX = Math_LerpAngle(last.HeadX, cur->HeadX, 0.5f);
mid.HeadY = Math_LerpAngle(last.HeadY, cur->HeadY, 0.5f);
NetInterpComp_AddState(interp, mid);
NetInterpComp_AddState(interp, *cur);
/* Head rotation lags behind body a tiny bit */
InterpComp_AddRotY(&interp->Base, Math_LerpAngle(last.HeadY, cur->HeadY, 0.33333333f));
InterpComp_AddRotY(&interp->Base, Math_LerpAngle(last.HeadY, cur->HeadY, 0.66666667f));
InterpComp_AddRotY(&interp->Base, Math_LerpAngle(last.HeadY, cur->HeadY, 1.00000000f));
}
}
void NetInterpComp_AdvanceState(NetInterpComp* interp) {
interp->Base.Prev = interp->Base.Next;
if (interp->StatesCount > 0) {
interp->Base.Next = interp->States[0];
NetInterpComp_RemoveOldestState(interp);
}
InterpComp_AdvanceRotY(&interp->Base);
}
Real32 LocalInterpComp_Next(Real32 next, Real32 cur, Real32* last, bool interpolate) {
if (next == LOCATIONUPDATE_EXCLUDED) return cur;
if (!interpolate) *last = next;
return next;
}
void LocalInterpComp_SetLocation(InterpComp* interp, LocationUpdate* update, bool interpolate) {
Entity* entity = &LocalPlayer_Instance.Base.Base;
InterpState* prev = &interp->Prev;
InterpState* next = &interp->Next;
if (update->IncludesPosition) {
InterpComp_SetPos(next, update);
Real32 blockOffset = next->Pos.Y - Math_Floor(next->Pos.Y);
if (blockOffset < ENTITY_ADJUSTMENT) {
next->Pos.Y += ENTITY_ADJUSTMENT;
}
if (!interpolate) {
prev->Pos = next->Pos;
entity->Position = next->Pos;
UInt32 i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (Entities_List[i] == NULL) continue;
if ((i == closestId || allNames) && i != ENTITIES_SELF_ID) {
Entities_List[i]->RenderName(Entities_List[i]);
}
}
next->RotX = LocalInterpComp_Next(update->RotX, next->RotX, &prev->RotX, interpolate);
next->RotZ = LocalInterpComp_Next(update->RotZ, next->RotZ, &prev->RotZ, interpolate);
next->HeadX = LocalInterpComp_Next(update->HeadX, next->HeadX, &prev->HeadX, interpolate);
next->HeadY = LocalInterpComp_Next(update->RotY, next->HeadY, &prev->HeadY, interpolate);
if (update->RotY != LOCATIONUPDATE_EXCLUDED) {
if (!interpolate) {
interp->NextRotY = update->RotY;
entity->RotY = update->RotY;
interp->RotYCount = 0;
} else {
/* Body Y rotation lags slightly behind */
InterpComp_AddRotY(interp, Math_LerpAngle(prev->HeadY, next->HeadY, 0.33333333f));
InterpComp_AddRotY(interp, Math_LerpAngle(prev->HeadY, next->HeadY, 0.66666667f));
InterpComp_AddRotY(interp, Math_LerpAngle(prev->HeadY, next->HeadY, 1.00000000f));
interp->NextRotY = interp->RotYStates[0];
}
}
InterpComp_LerpAngles(interp, entity, 0.0f);
Gfx_SetTexturing(false);
Gfx_SetAlphaTest(false);
Gfx_SetDepthTest(true);
if (hadFog) Gfx_SetFog(true);
}
void LocalInterpComp_AdvanceState(InterpComp* interp) {
Entity* entity = &LocalPlayer_Instance.Base.Base;
interp->Prev = interp->Next;
entity->Position = interp->Next.Pos;
InterpComp_AdvanceRotY(interp);
void Entities_ContextLost(void) {
UInt32 i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (Entities_List[i] == NULL) continue;
Entities_List[i]->ContextLost(Entities_List[i]);
}
}
enum NameMode { Hovered, All, AllHovered, AllUnscaled }
void Entities_ContextRecreated(void) {
UInt32 i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (Entities_List[i] == NULL) continue;
Entities_List[i]->ContextRecreated(Entities_List[i]);
}
}
enum EntityShadow { None, SnapToBlock, Circle, CircleAll, }
void Entities_ChatFontChanged(void) {
UInt32 i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (Entities_List[i] == NULL) continue;
Player p = List[i] as Player;
if (p != null) p.UpdateName();
}
}
const int MaxCount = 256;
const byte SelfID = 255;
void Entities_Init(void) {
Event_RegisterVoid(&GfxEvents_ContextLost, Entities_ContextLost);
Event_RegisterVoid(&GfxEvents_ContextRecreated, Entities_ContextRecreated);
Event_RegisterVoid(&ChatEvents_FontChanged, Entities_ChatFontChanged);
public Entity[] List = new Entity[MaxCount];
public EntityShadow ShadowMode = EntityShadow.None;
byte closestId;
NameMode NamesMode = NameMode.Hovered;
Entities_NameMode = Options_GetEnum(OptionsKey.NamesMode, NameMode.Hovered);
if (Game_ClassicMode) Entities_NameMode = NAME_MODE_HOVERED;
Entities_ShadowMode = Options_GetEnum(OptionsKey.EntityShadow, EntityShadow.None);
if (Game_ClassicMode) Entities_ShadowMode = SHADOW_MODE_NONE;
}
void Entities_Init(void) {
game.Graphics.ContextLost += ContextLost;
game.Graphics.ContextRecreated += ContextRecreated;
game.Events.ChatFontChanged += ChatFontChanged;
NamesMode = Options.GetEnum(OptionsKey.NamesMode, NameMode.Hovered);
if (game.ClassicMode) NamesMode = NameMode.Hovered;
ShadowMode = Options.GetEnum(OptionsKey.EntityShadow, EntityShadow.None);
if (game.ClassicMode) ShadowMode = EntityShadow.None;
void Entities_Free(void) {
UInt32 i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (Entities_List[i] == NULL) continue;
Entities_Remove((EntityID)i);
}
void Entities_Tick(ScheduledTask* task) {
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
List[i].Tick(task.Interval);
Event_UnregisterVoid(&GfxEvents_ContextLost, Entities_ContextLost);
Event_UnregisterVoid(&GfxEvents_ContextRecreated, Entities_ContextRecreated);
Event_UnregisterVoid(&ChatEvents_FontChanged, Entities_ChatFontChanged);
if (ShadowComponent.shadowTex > 0) {
game.Graphics.DeleteTexture(ref ShadowComponent.shadowTex);
}
}
void Entities_Remove(EntityID id) {
Event_RaiseEntityID(&EntityEvents_Removed, id);
Entities_List[id]->Despawn(Entities_List[id]);
Entities_List[id] = NULL;
}
EntityID Entities_GetCloset(Entity* src) {
Vector3 eyePos = Entity_GetEyePosition(src);
Vector3 dir = Vector3_GetDirVector(src->HeadY * MATH_DEG2RAD, src->HeadX * MATH_DEG2RAD);
float closestDist = float.PositiveInfinity;
EntityID targetId = ENTITIES_SELF_ID;
UInt32 i;
for (i = 0; i < ENTITIES_SELF_ID; i++) { /* -1 because we don't want to pick against local player */
Entity* entity = Entities_List[i];
if (entity == NULL) continue;
Real32 t0, t1;
if (Intersection_RayIntersectsRotatedBox(eyePos, dir, entity, &t0, &t1) && t0 < closestDist) {
closestDist = t0;
targetId = (EntityID)i;
}
}
return targetId;
}
void Entities_RenderModels(Real64 delta, Real32 t) {
gfx.Texturing = true;
gfx.AlphaTest = true;
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
List[i].RenderModel(delta, t);
}
gfx.Texturing = false;
gfx.AlphaTest = false;
}
bool hadFog;
void Entities_DrawShadows(void) {
if (Entities_ShadowMode == SHADOW_MODE_NONE) return;
ShadowComponent.boundShadowTex = false;
void Entities_RenderNames(Real64 delta) {
closestId = GetClosetPlayer(game.LocalPlayer);
if (!game.LocalPlayer.Hacks.CanSeeAllNames || NamesMode != NameMode.All) return;
Gfx_SetAlphaArgBlend(true);
Gfx_SetDepthWrite(false);
Gfx_SetAlphaBlending(true);
Gfx_SetTexturing(true);
gfx.Texturing = true;
gfx.AlphaTest = true;
hadFog = gfx.Fog;
if (hadFog) gfx.Fog = false;
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
if (i != closestId || i == SelfID)
List[i].RenderName();
}
gfx.Texturing = false;
gfx.AlphaTest = false;
if (hadFog) gfx.Fog = true;
}
void Entities_RenderHoveredNames(Real64 delta) {
gfx.Texturing = true;
gfx.AlphaTest = true;
gfx.DepthTest = false;
hadFog = gfx.Fog;
if (hadFog) gfx.Fog = false;
bool allNames = !(NamesMode == NameMode.Hovered || NamesMode == NameMode.All)
&& game.LocalPlayer.Hacks.CanSeeAllNames;
for (int i = 0; i < List.Length; i++) {
bool hover = (i == closestId || allNames) && i != SelfID;
if (List[i] != null && hover)
List[i].RenderName();
}
gfx.Texturing = false;
gfx.AlphaTest = false;
gfx.DepthTest = true;
if (hadFog) gfx.Fog = true;
}
void Entities_ContextLost(void) {
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
List[i].ContextLost();
}
}
void Entities_ContextRecreated(void) {
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
List[i].ContextRecreated();
}
}
void Entities_ChatFontChanged(void) {
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B);
ShadowComponent.Draw(Entities_List[ENTITIES_SELF_ID]);
if (Entities_ShadowMode == SHADOW_MODE_CIRCLE_ALL) {
UInt32 i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (Entities_List[i] == NULL) continue;
Player p = List[i] as Player;
if (p != null) p.UpdateName();
if (p != null) ShadowComponent.Draw(p);
}
}
void Entities_Remove(EntityID id) {
game.EntityEvents.RaiseRemoved(id);
List[id].Despawn();
List[id] = null;
}
void Entities_Free(void) {
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
RemoveEntity((byte)i);
}
game.Graphics.ContextLost -= ContextLost;
game.Graphics.ContextRecreated -= ContextRecreated;
game.Events.ChatFontChanged -= ChatFontChanged;
if (ShadowComponent.shadowTex > 0) {
game.Graphics.DeleteTexture(ref ShadowComponent.shadowTex);
}
}
EntityID Entities_GetClosetPlayer(Player* src) {
Vector3 eyePos = src.EyePosition;
Vector3 dir = Utils.GetDirVector(src.HeadYRadians, src.HeadXRadians);
float closestDist = float.PositiveInfinity;
byte targetId = SelfID;
for (int i = 0; i < List.Length - 1; i++) { // -1 because we don't want to pick against local player
Entity p = List[i];
if (p == null) continue;
float t0, t1;
if (Intersection.RayIntersectsRotatedBox(eyePos, dir, p, out t0, out t1) && t0 < closestDist) {
closestDist = t0;
targetId = (byte)i;
}
}
return targetId;
}
void Entities_DrawShadows(void) {
if (ShadowMode == EntityShadow.None) return;
ShadowComponent.boundShadowTex = false;
IGraphicsApi gfx = game.Graphics;
gfx.AlphaArgBlend = true;
gfx.DepthWrite = false;
gfx.AlphaBlending = true;
gfx.Texturing = true;
gfx.SetBatchFormat(VertexFormat.P3fT2fC4b);
ShadowComponent.Draw(game, List[SelfID]);
if (ShadowMode == EntityShadow.CircleAll)
DrawOtherShadows();
gfx.AlphaArgBlend = false;
gfx.DepthWrite = true;
gfx.AlphaBlending = false;
gfx.Texturing = false;
}
void Entities_DrawOtherShadows(void) {
for (int i = 0; i < SelfID; i++) {
if (List[i] == null) continue;
Player p = List[i] as Player;
if (p != null) ShadowComponent.Draw(game, p);
}
}
Gfx_SetAlphaArgBlend(false);
Gfx_SetDepthWrite(true);
Gfx_SetAlphaBlending(false);
Gfx_SetTexturing(false);
}

View File

@ -1,12 +1,14 @@
#ifndef CC_ENTITY_H
#define CC_ENTITY_H
#include "EntityComponents.h"
#include "IModel.h"
#include "Typedefs.h"
#include "Vectors.h"
#include "AABB.h"
#include "GraphicsEnums.h"
#include "Matrix.h"
/* Represents an in-game entity. Also contains various components for entities.
#include "GameStructs.h"
/* Represents an in-game entity.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/
typedef struct IModel_ IModel; /* Forward declaration */
@ -18,6 +20,21 @@ typedef struct IModel_ IModel; /* Forward declaration */
/* Maxmimum number of characters in a model name. */
#define ENTITY_MAX_MODEL_LENGTH 10
#define ENTITIES_MAX_COUNT 256
#define ENTITIES_SELF_ID 255
UInt32 Entities_NameMode;
#define NAME_MODE_HOVERED 0
#define NAME_MODE_ALL 1
#define NAME_MODE_ALL_HOVERED 2
#define NAME_MODE_ALL_UNSCALED 3
UInt32 Entities_ShadowMode;
#define SHADOW_MODE_NONE 0
#define SHADOW_MODE_SNAP_TO_BLOCK 1
#define SHADOW_MODE_CIRCLE 2
#define SHADOW_MODE_CIRCLE_ALL 3
typedef bool (*TouchesAny_Condition)(BlockID block);
/* Represents a location update for an entity. Can be a relative position, full position, and/or an orientation update. */
@ -39,22 +56,6 @@ void LocationUpdate_MakeOri(LocationUpdate* update, Real32 rotY, Real32 headX);
void LocationUpdate_MakePos(LocationUpdate* update, Vector3 pos, bool rel);
void LocationUpdate_MakePosAndOri(LocationUpdate* update, Vector3 pos, Real32 rotY, Real32 headX, bool rel);
/* Entity component that performs model animation depending on movement speed and time. */
typedef struct AnimatedComp_ {
Real32 BobbingHor, BobbingVer, BobbingModel;
Real32 WalkTime, Swing, BobStrength;
Real32 WalkTimeO, WalkTimeN, SwingO, SwingN, BobStrengthO, BobStrengthN;
Real32 LeftLegX, LeftLegZ, RightLegX, RightLegZ;
Real32 LeftArmX, LeftArmZ, RightArmX, RightArmZ;
} AnimatedComp;
void AnimatedComp_Init(AnimatedComp* anim);
void AnimatedComp_Update(AnimatedComp* anim, Vector3 oldPos, Vector3 newPos, Real64 delta, bool onGround);
void AnimatedComp_GetCurrent(AnimatedComp* anim, Real32 t, bool calcHumanAnims);
/* Contains a model, along with position, velocity, and rotation. May also contain other fields and properties. */
typedef struct Entity_ {
Vector3 Position;
@ -77,7 +78,13 @@ typedef struct Entity_ {
bool NoShade;
/* TODO: SHOULD THESE BE A SEPARATE VTABLE STRUCT? (only need 1 shared pointer that way) */
void (*Tick)(struct Entity_* entity, ScheduledTask* task);
void (*SetLocation)(struct Entity_* entity, LocationUpdate* update, bool interpolate);
void (*RenderModel)(struct Entity_* entity, Real64 deltaTime, Real32 t);
void (*RenderName)(struct Entity_* entity);
void (*ContextLost)(struct Entity_* entity);
void (*ContextRecreated)(struct Entity_* entity);
void (*Despawn)(struct Entity_* entity);
PackedCol (*GetCol)(struct Entity_* entity);
} Entity;
@ -93,85 +100,14 @@ bool Entity_TouchesAnyRope(Entity* entity);
bool Entity_TouchesAnyLava(Entity* entity);
bool Entity_TouchesAnyWater(Entity* entity);
/* Entity component that performs tilt animation depending on movement speed and time. */
typedef struct TiltComp_ {
Real32 TiltX, TiltY, VelTiltStrength;
Real32 VelTiltStrengthO, VelTiltStrengthN;
} TiltComp;
void TiltComp_Init(TiltComp* anim);
void TiltComp_Update(TiltComp* anim, Real64 delta);
void TiltComp_GetCurrent(TiltComp* anim, Real32 t);
/* Entity component that performs management of hack states. */
typedef struct HacksComponent_ {
UInt8 UserType;
/* Speed player move at, relative to normal speed, when the 'speeding' key binding is held down. */
Real32 SpeedMultiplier;
/* Whether blocks that the player places that intersect themselves, should cause the player to
be pushed back in the opposite direction of the placed block. */
bool PushbackPlacing;
/* Whether the player should be able to step up whole blocks, instead of just slabs. */
bool FullBlockStep;
/* Whether the player has allowed hacks usage as an option. Note 'can use X' set by the server override this. */
bool Enabled;
bool CanAnyHacks, CanUseThirdPersonCamera, CanSpeed, CanFly;
bool CanRespawn, CanNoclip, CanPushbackBlocks,CanSeeAllNames;
bool CanDoubleJump, CanBePushed;
/* Maximum speed the entity can move at horizontally when CanSpeed is false. */
Real32 BaseHorSpeed;
/* Max amount of jumps the player can perform. */
Int32 MaxJumps;
/* Whether the player should slide after letting go of movement buttons in noclip. */
bool NoclipSlide;
/* Whether the player has allowed the usage of fast double jumping abilities. */
bool WOMStyleHacks;
bool Noclip, Flying,FlyingUp, FlyingDown, Speeding, HalfSpeeding;
UInt8 HacksFlagsBuffer[String_BufferSize(128)];
String HacksFlags;
} HacksComp;
void HacksComp_Init(HacksComp* hacks);
bool HacksComp_CanJumpHigher(HacksComp* hacks);
bool HacksComp_Floating(HacksComp* hacks);
void HacksComp_SetUserType(HacksComp* hacks, UInt8 value);
void HacksComp_CheckConsistency(HacksComp* hacks);
void HacksComp_UpdateState(HacksComp* hacks);
/* Represents a position and orientation state. */
typedef struct InterpState_ {
Vector3 Pos;
Real32 HeadX, HeadY, RotX, RotZ;
} InterpState;
/* Base entity component that performs interpolation of position and orientation. */
typedef struct InterpComp_ {
InterpState Prev, Next;
Real32 PrevRotY, NextRotY;
Int32 RotYCount;
Real32 RotYStates[15];
} InterpComp;
void InterpComp_LerpAngles(InterpComp* interp, Entity* entity, Real32 t);
void LocalInterpComp_SetLocation(InterpComp* interp, LocationUpdate* update, bool interpolate);
void LocalInterpComp_AdvanceState(InterpComp* interp);
/* Entity component that performs interpolation for network players. */
typedef struct NetInterpComp_ {
InterpComp Base;
/* Last known position and orientation sent by the server. */
InterpState Cur;
Int32 StatesCount;
InterpState States[10];
} NetInterpComp;
void NetInterpComp_SetLocation(NetInterpComp* interp, LocationUpdate* update, bool interpolate);
void NetInterpComp_AdvanceState(NetInterpComp* interp);
Entity* Entities_List[ENTITIES_MAX_COUNT];
void Entities_Tick(ScheduledTask* task);
void Entities_RenderModels(Real64 delta, Real32 t);
void Entities_RenderNames(Real64 delta);
void Entities_RenderHoveredNames(Real64 delta);
void Entities_Init(void);
void Entities_Free(void);
void Entities_Remove(EntityID id);
EntityID Entities_GetCloset(Entity* src);
void Entities_DrawShadows(void);
#endif

View File

@ -0,0 +1,438 @@
#include "EntityComponents.h"
#include "ExtMath.h"
#include "World.h"
#include "Block.h"
#include "Event.h"
#include "Game.h"
#include "Player.h"
#include "Platform.h"
#include "Camera.h"
#include "Funcs.h"
#define ANIM_MAX_ANGLE (110 * MATH_DEG2RAD)
#define ANIM_ARM_MAX (60.0f * MATH_DEG2RAD)
#define ANIM_LEG_MAX (80.0f * MATH_DEG2RAD)
#define ANIM_IDLE_MAX (3.0f * MATH_DEG2RAD)
#define ANIM_IDLE_XPERIOD (2.0f * MATH_PI / 5.0f)
#define ANIM_IDLE_ZPERIOD (2.0f * MATH_PI / 3.5f)
void AnimatedComp_DoTilt(Real32* tilt, bool reduce) {
if (reduce) {
(*tilt) *= 0.84f;
} else {
(*tilt) += 0.1f;
}
Math_Clamp(*tilt, 0.0f, 1.0f);
}
void AnimatedComp_PerpendicularAnim(AnimatedComp* anim, Real32 flapSpeed, Real32 idleXRot, Real32 idleZRot, bool left) {
Real32 verAngle = 0.5f + 0.5f * Math_Sin(anim->WalkTime * flapSpeed);
Real32 zRot = -idleZRot - verAngle * anim->Swing * ANIM_MAX_ANGLE;
Real32 horAngle = Math_Cos(anim->WalkTime) * anim->Swing * ANIM_ARM_MAX * 1.5f;
Real32 xRot = idleXRot + horAngle;
if (left) {
anim->LeftArmX = xRot; anim->LeftArmZ = zRot;
} else {
anim->RightArmX = xRot; anim->RightArmZ = zRot;
}
}
void AnimatedComp_CalcHumanAnim(AnimatedComp* anim, Real32 idleXRot, Real32 idleZRot) {
AnimatedComp_PerpendicularAnim(anim, 0.23f, idleXRot, idleZRot, true);
AnimatedComp_PerpendicularAnim(anim, 0.28f, idleXRot, idleZRot, false);
anim->RightArmX = -anim->RightArmX; anim->RightArmZ = -anim->RightArmZ;
}
void AnimatedComp_Init(AnimatedComp* anim) {
anim->BobbingHor = 0.0f; anim->BobbingVer = 0.0f; anim->BobbingModel = 0.0f;
anim->WalkTime = 0.0f; anim->Swing = 0.0f; anim->BobStrength = 1.0f;
anim->WalkTimeO = 0.0f; anim->SwingO = 0.0f; anim->BobStrengthO = 1.0f;
anim->WalkTimeN = 0.0f; anim->SwingN = 0.0f; anim->BobStrengthN = 1.0f;
anim->LeftLegX = 0.0f; anim->LeftLegZ = 0.0f; anim->RightLegX = 0.0f; anim->RightLegZ = 0.0f;
anim->LeftArmX = 0.0f; anim->LeftArmZ = 0.0f; anim->RightArmX = 0.0f; anim->RightArmZ = 0.0f;
}
void AnimatedComp_Update(AnimatedComp* anim, Vector3 oldPos, Vector3 newPos, Real64 delta, bool onGround) {
anim->WalkTimeO = anim->WalkTimeN;
anim->SwingO = anim->SwingN;
Real32 dx = newPos.X - oldPos.X;
Real32 dz = newPos.Z - oldPos.Z;
Real32 distance = Math_Sqrt(dx * dx + dz * dz);
if (distance > 0.05f) {
Real32 walkDelta = distance * 2 * (Real32)(20 * delta);
anim->WalkTimeN += walkDelta;
anim->SwingN += (Real32)delta * 3;
} else {
anim->SwingN -= (Real32)delta * 3;
}
Math_Clamp(anim->SwingN, 0.0f, 1.0f);
/* TODO: the Tilt code was designed for 60 ticks/second, fix it up for 20 ticks/second */
anim->BobStrengthO = anim->BobStrengthN;
Int32 i;
for (i = 0; i < 3; i++) {
AnimatedComp_DoTilt(&anim->BobStrengthN, !Game_ViewBobbing || !onGround);
}
}
void AnimatedComp_GetCurrent(AnimatedComp* anim, Real32 t, bool calcHumanAnims) {
anim->Swing = Math_Lerp(anim->SwingO, anim->SwingN, t);
anim->WalkTime = Math_Lerp(anim->WalkTimeO, anim->WalkTimeN, t);
anim->BobStrength = Math_Lerp(anim->BobStrengthO, anim->BobStrengthN, t);
Real32 idleTime = (Real32)Game_Accumulator;
Real32 idleXRot = Math_Sin(idleTime * ANIM_IDLE_XPERIOD) * ANIM_IDLE_MAX;
Real32 idleZRot = ANIM_IDLE_MAX + Math_Cos(idleTime * ANIM_IDLE_ZPERIOD) * ANIM_IDLE_MAX;
anim->LeftArmX = (Math_Cos(anim->WalkTime) * anim->Swing * ANIM_ARM_MAX) - idleXRot;
anim->LeftArmZ = -idleZRot;
anim->LeftLegX = -(Math_Cos(anim->WalkTime) * anim->Swing * ANIM_LEG_MAX);
anim->LeftLegZ = 0;
anim->RightLegX = -anim->LeftLegX; anim->RightLegZ = -anim->LeftLegZ;
anim->RightArmX = -anim->LeftArmX; anim->RightArmZ = -anim->LeftArmZ;
anim->BobbingHor = Math_Cos(anim->WalkTime) * anim->Swing * (2.5f / 16.0f);
anim->BobbingVer = Math_AbsF(Math_Sin(anim->WalkTime)) * anim->Swing * (2.5f / 16.0f);
anim->BobbingModel = Math_AbsF(Math_Cos(anim->WalkTime)) * anim->Swing * (4.0f / 16.0f);
if (calcHumanAnims && !Game_SimpleArmsAnim) {
AnimatedComp_CalcHumanAnim(anim, idleXRot, idleZRot);
}
}
void TiltComp_Init(TiltComp* anim) {
anim->TiltX = 0.0f; anim->TiltY = 0.0f; anim->VelTiltStrength = 1.0f;
anim->VelTiltStrengthO = 1.0f; anim->VelTiltStrengthN = 1.0f;
}
void TiltComp_Update(TiltComp* anim, Real64 delta) {
anim->VelTiltStrengthO = anim->VelTiltStrengthN;
LocalPlayer* p = &LocalPlayer_Instance;
/* TODO: the Tilt code was designed for 60 ticks/second, fix it up for 20 ticks/second */
Int32 i;
for (i = 0; i < 3; i++) {
AnimatedComp_DoTilt(&anim->VelTiltStrengthN, p->Hacks.Noclip || p->Hacks.Flying);
}
}
void TiltComp_GetCurrent(TiltComp* anim, Real32 t) {
LocalPlayer* p = &LocalPlayer_Instance;
anim->VelTiltStrength = Math_Lerp(anim->VelTiltStrengthO, anim->VelTiltStrengthN, t);
AnimatedComp* pAnim = &p->Base.Base.Anim;
anim->TiltX = Math_Cos(pAnim->WalkTime) * pAnim->Swing * (0.15f * MATH_DEG2RAD);
anim->TiltY = Math_Sin(pAnim->WalkTime) * pAnim->Swing * (0.15f * MATH_DEG2RAD);
}
void HacksComp_SetAll(HacksComp* hacks, bool allowed) {
hacks->CanAnyHacks = allowed; hacks->CanFly = allowed;
hacks->CanNoclip = allowed; hacks->CanRespawn = allowed;
hacks->CanSpeed = allowed; hacks->CanPushbackBlocks = allowed;
hacks->CanUseThirdPersonCamera = allowed;
}
void HacksComp_Init(HacksComp* hacks) {
Platform_MemSet(hacks, 0, sizeof(HacksComp));
HacksComp_SetAll(hacks, true);
hacks->SpeedMultiplier = 10.0f;
hacks->Enabled = true;
hacks->CanSeeAllNames = true;
hacks->CanDoubleJump = true;
hacks->BaseHorSpeed = 1.0f;
hacks->MaxJumps = 1;
hacks->NoclipSlide = true;
hacks->CanBePushed = true;
hacks->HacksFlags = String_InitAndClear(&hacks->HacksFlagsBuffer[0], 128);
}
bool HacksComp_CanJumpHigher(HacksComp* hacks) {
return hacks->Enabled && hacks->CanAnyHacks && hacks->CanSpeed;
}
bool HacksComp_Floating(HacksComp* hacks) {
return hacks->Noclip || hacks->Flying;
}
String HacksComp_GetFlagValue(String* flag, HacksComp* hacks) {
String* joined = &hacks->HacksFlags;
Int32 start = String_IndexOfString(joined, flag);
if (start < 0) return String_MakeNull();
start += flag->length;
Int32 end = String_IndexOf(joined, ' ', start);
if (end < 0) end = joined->length;
return String_UNSAFE_Substring(joined, start, end - start);
}
void HacksComp_ParseHorizontalSpeed(HacksComp* hacks) {
String horSpeedFlag = String_FromConst("horspeed=");
String speedStr = HacksComp_GetFlagValue(&horSpeedFlag, hacks);
if (speedStr.length == 0) return;
Real32 speed = 0.0f;
if (!Convert_TryParseReal32(&speedStr, &speed) || speed <= 0.0f) return;
hacks->BaseHorSpeed = speed;
}
void HacksComp_ParseMultiSpeed(HacksComp* hacks) {
String jumpsFlag = String_FromConst("jumps=");
String jumpsStr = HacksComp_GetFlagValue(&jumpsFlag, hacks);
if (jumpsStr.length == 0) return;
Int32 jumps = 0;
if (!Convert_TryParseInt32(&jumpsStr, &jumps) || jumps < 0) return;
hacks->MaxJumps = jumps;
}
void HacksComp_ParseFlag(HacksComp* hacks, const UInt8* incFlag, const UInt8* excFlag, bool* target) {
String include = String_FromReadonly(incFlag);
String exclude = String_FromReadonly(excFlag);
String* joined = &hacks->HacksFlags;
if (String_ContainsString(joined, &include)) {
*target = true;
} else if (String_ContainsString(joined, &exclude)) {
*target = false;
}
}
void HacksComp_ParseAllFlag(HacksComp* hacks, const UInt8* incFlag, const UInt8* excFlag) {
String include = String_FromReadonly(incFlag);
String exclude = String_FromReadonly(excFlag);
String* joined = &hacks->HacksFlags;
if (String_ContainsString(joined, &include)) {
HacksComp_SetAll(hacks, true);
} else if (String_ContainsString(joined, &exclude)) {
HacksComp_SetAll(hacks, false);
}
}
void HacksComp_SetUserType(HacksComp* hacks, UInt8 value) {
bool isOp = value >= 100 && value <= 127;
hacks->UserType = value;
hacks->CanSeeAllNames = isOp;
Block_CanPlace[BLOCK_BEDROCK] = isOp;
Block_CanDelete[BLOCK_BEDROCK] = isOp;
Block_CanPlace[BLOCK_WATER] = isOp;
Block_CanPlace[BLOCK_STILL_WATER] = isOp;
Block_CanPlace[BLOCK_LAVA] = isOp;
Block_CanPlace[BLOCK_STILL_LAVA] = isOp;
}
void HacksComp_CheckConsistency(HacksComp* hacks) {
if (!hacks->CanFly || !hacks->Enabled) {
hacks->Flying = false; hacks->FlyingDown = false; hacks->FlyingUp = false;
}
if (!hacks->CanNoclip || !hacks->Enabled) {
hacks->Noclip = false;
}
if (!hacks->CanSpeed || !hacks->Enabled) {
hacks->Speeding = false; hacks->HalfSpeeding = false;
}
hacks->CanDoubleJump = hacks->CanAnyHacks && hacks->Enabled && hacks->CanSpeed;
hacks->CanSeeAllNames = hacks->CanAnyHacks && hacks->CanSeeAllNames;
if (!hacks->CanUseThirdPersonCamera || !hacks->Enabled) {
Camera_CycleActive();
}
}
void HacksComp_UpdateState(HacksComp* hacks) {
HacksComp_SetAll(hacks, true);
if (hacks->HacksFlags.length == 0) return;
hacks->BaseHorSpeed = 1;
hacks->MaxJumps = 1;
hacks->CanBePushed = true;
/* By default (this is also the case with WoM), we can use hacks. */
String excHacks = String_FromConst("-hax");
if (String_ContainsString(&hacks->HacksFlags, &excHacks)) {
HacksComp_SetAll(hacks, false);
}
HacksComp_ParseFlag(hacks, "+fly", "-fly", &hacks->CanFly);
HacksComp_ParseFlag(hacks, "+noclip", "-noclip", &hacks->CanNoclip);
HacksComp_ParseFlag(hacks, "+speed", "-speed", &hacks->CanSpeed);
HacksComp_ParseFlag(hacks, "+respawn", "-respawn", &hacks->CanRespawn);
HacksComp_ParseFlag(hacks, "+push", "-push", &hacks->CanBePushed);
if (hacks->UserType == 0x64) {
HacksComp_ParseAllFlag(hacks, "+ophax", "-ophax");
}
HacksComp_ParseHorizontalSpeed(hacks);
HacksComp_ParseMultiSpeed(hacks);
HacksComp_CheckConsistency(hacks);
Event_RaiseVoid(&UserEvents_HackPermissionsChanged);
}
void InterpComp_RemoveOldestRotY(InterpComp* interp) {
Int32 i;
for (i = 0; i < Array_NumElements(interp->RotYStates); i++) {
interp->RotYStates[i] = interp->RotYStates[i + 1];
}
interp->RotYCount--;
}
void InterpComp_AddRotY(InterpComp* interp, Real32 state) {
if (interp->RotYCount == Array_NumElements(interp->RotYStates)) {
InterpComp_RemoveOldestRotY(interp);
}
interp->RotYStates[interp->RotYCount] = state; interp->RotYCount++;
}
void InterpComp_AdvanceRotY(InterpComp* interp) {
interp->PrevRotY = interp->NextRotY;
if (interp->RotYCount == 0) return;
interp->NextRotY = interp->RotYStates[0];
InterpComp_RemoveOldestRotY(interp);
}
void InterpComp_LerpAngles(InterpComp* interp, Entity* entity, Real32 t) {
InterpState* prev = &interp->Prev;
InterpState* next = &interp->Next;
entity->HeadX = Math_LerpAngle(prev->HeadX, next->HeadX, t);
entity->HeadY = Math_LerpAngle(prev->HeadY, next->HeadY, t);
entity->RotX = Math_LerpAngle(prev->RotX, next->RotX, t);
entity->RotY = Math_LerpAngle(interp->PrevRotY, interp->NextRotY, t);
entity->RotZ = Math_LerpAngle(prev->RotZ, next->RotZ, t);
}
void InterpComp_SetPos(InterpState* state, LocationUpdate* update) {
if (update->RelativePosition) {
Vector3_Add(&state->Pos, &state->Pos, &update->Pos);
} else {
state->Pos = update->Pos;
}
}
Real32 NetInterpComp_Next(Real32 next, Real32 cur) {
if (next == LOCATIONUPDATE_EXCLUDED) return cur;
return next;
}
void NetInterpComp_RemoveOldestState(NetInterpComp* interp) {
Int32 i;
for (i = 0; i < Array_NumElements(interp->States); i++) {
interp->States[i] = interp->States[i + 1];
}
interp->StatesCount--;
}
void NetInterpComp_AddState(NetInterpComp* interp, InterpState state) {
if (interp->StatesCount == Array_NumElements(interp->States)) {
NetInterpComp_RemoveOldestState(interp);
}
interp->States[interp->StatesCount] = state; interp->StatesCount++;
}
void NetInterpComp_SetLocation(NetInterpComp* interp, LocationUpdate* update, bool interpolate) {
InterpState last = interp->Cur;
InterpState* cur = &interp->Cur;
if (update->IncludesPosition) {
InterpComp_SetPos(cur, update);
}
cur->RotX = NetInterpComp_Next(update->RotX, cur->RotX);
cur->RotZ = NetInterpComp_Next(update->RotZ, cur->RotZ);
cur->HeadX = NetInterpComp_Next(update->HeadX, cur->HeadX);
cur->HeadY = NetInterpComp_Next(update->RotY, cur->HeadY);
if (!interpolate) {
interp->Base.Prev = *cur; interp->Base.PrevRotY = cur->HeadY;
interp->Base.Next = *cur; interp->Base.NextRotY = cur->HeadY;
interp->Base.RotYCount = 0; interp->StatesCount = 0;
} else {
/* Smoother interpolation by also adding midpoint. */
InterpState mid;
Vector3_Lerp(&mid.Pos, &last.Pos, &cur->Pos, 0.5f);
mid.RotX = Math_LerpAngle(last.RotX, cur->RotX, 0.5f);
mid.RotZ = Math_LerpAngle(last.RotZ, cur->RotZ, 0.5f);
mid.HeadX = Math_LerpAngle(last.HeadX, cur->HeadX, 0.5f);
mid.HeadY = Math_LerpAngle(last.HeadY, cur->HeadY, 0.5f);
NetInterpComp_AddState(interp, mid);
NetInterpComp_AddState(interp, *cur);
/* Head rotation lags behind body a tiny bit */
InterpComp_AddRotY(&interp->Base, Math_LerpAngle(last.HeadY, cur->HeadY, 0.33333333f));
InterpComp_AddRotY(&interp->Base, Math_LerpAngle(last.HeadY, cur->HeadY, 0.66666667f));
InterpComp_AddRotY(&interp->Base, Math_LerpAngle(last.HeadY, cur->HeadY, 1.00000000f));
}
}
void NetInterpComp_AdvanceState(NetInterpComp* interp) {
interp->Base.Prev = interp->Base.Next;
if (interp->StatesCount > 0) {
interp->Base.Next = interp->States[0];
NetInterpComp_RemoveOldestState(interp);
}
InterpComp_AdvanceRotY(&interp->Base);
}
Real32 LocalInterpComp_Next(Real32 next, Real32 cur, Real32* last, bool interpolate) {
if (next == LOCATIONUPDATE_EXCLUDED) return cur;
if (!interpolate) *last = next;
return next;
}
void LocalInterpComp_SetLocation(InterpComp* interp, LocationUpdate* update, bool interpolate) {
Entity* entity = &LocalPlayer_Instance.Base.Base;
InterpState* prev = &interp->Prev;
InterpState* next = &interp->Next;
if (update->IncludesPosition) {
InterpComp_SetPos(next, update);
Real32 blockOffset = next->Pos.Y - Math_Floor(next->Pos.Y);
if (blockOffset < ENTITY_ADJUSTMENT) {
next->Pos.Y += ENTITY_ADJUSTMENT;
}
if (!interpolate) {
prev->Pos = next->Pos;
entity->Position = next->Pos;
}
}
next->RotX = LocalInterpComp_Next(update->RotX, next->RotX, &prev->RotX, interpolate);
next->RotZ = LocalInterpComp_Next(update->RotZ, next->RotZ, &prev->RotZ, interpolate);
next->HeadX = LocalInterpComp_Next(update->HeadX, next->HeadX, &prev->HeadX, interpolate);
next->HeadY = LocalInterpComp_Next(update->RotY, next->HeadY, &prev->HeadY, interpolate);
if (update->RotY != LOCATIONUPDATE_EXCLUDED) {
if (!interpolate) {
interp->NextRotY = update->RotY;
entity->RotY = update->RotY;
interp->RotYCount = 0;
} else {
/* Body Y rotation lags slightly behind */
InterpComp_AddRotY(interp, Math_LerpAngle(prev->HeadY, next->HeadY, 0.33333333f));
InterpComp_AddRotY(interp, Math_LerpAngle(prev->HeadY, next->HeadY, 0.66666667f));
InterpComp_AddRotY(interp, Math_LerpAngle(prev->HeadY, next->HeadY, 1.00000000f));
interp->NextRotY = interp->RotYStates[0];
}
}
InterpComp_LerpAngles(interp, entity, 0.0f);
}
void LocalInterpComp_AdvanceState(InterpComp* interp) {
Entity* entity = &LocalPlayer_Instance.Base.Base;
interp->Prev = interp->Next;
entity->Position = interp->Next.Pos;
InterpComp_AdvanceRotY(interp);
}

View File

@ -0,0 +1,107 @@
#ifndef CC_ENTITY_COMPONENTS_H
#define CC_ENTITY_COMPONENTS_H
#include "Typedefs.h"
#include "Vectors.h"
#include "String.h"
/* Various components for entities.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/
typedef struct Entity_ Entity;
typedef struct LocationUpdate_ LocationUpdate;
/* Entity component that performs model animation depending on movement speed and time. */
typedef struct AnimatedComp_ {
Real32 BobbingHor, BobbingVer, BobbingModel;
Real32 WalkTime, Swing, BobStrength;
Real32 WalkTimeO, WalkTimeN, SwingO, SwingN, BobStrengthO, BobStrengthN;
Real32 LeftLegX, LeftLegZ, RightLegX, RightLegZ;
Real32 LeftArmX, LeftArmZ, RightArmX, RightArmZ;
} AnimatedComp;
void AnimatedComp_Init(AnimatedComp* anim);
void AnimatedComp_Update(AnimatedComp* anim, Vector3 oldPos, Vector3 newPos, Real64 delta, bool onGround);
void AnimatedComp_GetCurrent(AnimatedComp* anim, Real32 t, bool calcHumanAnims);
/* Entity component that performs tilt animation depending on movement speed and time. */
typedef struct TiltComp_ {
Real32 TiltX, TiltY, VelTiltStrength;
Real32 VelTiltStrengthO, VelTiltStrengthN;
} TiltComp;
void TiltComp_Init(TiltComp* anim);
void TiltComp_Update(TiltComp* anim, Real64 delta);
void TiltComp_GetCurrent(TiltComp* anim, Real32 t);
/* Entity component that performs management of hack states. */
typedef struct HacksComponent_ {
UInt8 UserType;
/* Speed player move at, relative to normal speed, when the 'speeding' key binding is held down. */
Real32 SpeedMultiplier;
/* Whether blocks that the player places that intersect themselves, should cause the player to
be pushed back in the opposite direction of the placed block. */
bool PushbackPlacing;
/* Whether the player should be able to step up whole blocks, instead of just slabs. */
bool FullBlockStep;
/* Whether the player has allowed hacks usage as an option. Note 'can use X' set by the server override this. */
bool Enabled;
bool CanAnyHacks, CanUseThirdPersonCamera, CanSpeed, CanFly;
bool CanRespawn, CanNoclip, CanPushbackBlocks,CanSeeAllNames;
bool CanDoubleJump, CanBePushed;
/* Maximum speed the entity can move at horizontally when CanSpeed is false. */
Real32 BaseHorSpeed;
/* Max amount of jumps the player can perform. */
Int32 MaxJumps;
/* Whether the player should slide after letting go of movement buttons in noclip. */
bool NoclipSlide;
/* Whether the player has allowed the usage of fast double jumping abilities. */
bool WOMStyleHacks;
bool Noclip, Flying,FlyingUp, FlyingDown, Speeding, HalfSpeeding;
UInt8 HacksFlagsBuffer[String_BufferSize(128)];
String HacksFlags;
} HacksComp;
void HacksComp_Init(HacksComp* hacks);
bool HacksComp_CanJumpHigher(HacksComp* hacks);
bool HacksComp_Floating(HacksComp* hacks);
void HacksComp_SetUserType(HacksComp* hacks, UInt8 value);
void HacksComp_CheckConsistency(HacksComp* hacks);
void HacksComp_UpdateState(HacksComp* hacks);
/* Represents a position and orientation state. */
typedef struct InterpState_ {
Vector3 Pos;
Real32 HeadX, HeadY, RotX, RotZ;
} InterpState;
/* Base entity component that performs interpolation of position and orientation. */
typedef struct InterpComp_ {
InterpState Prev, Next;
Real32 PrevRotY, NextRotY;
Int32 RotYCount;
Real32 RotYStates[15];
} InterpComp;
void InterpComp_LerpAngles(InterpComp* interp, Entity* entity, Real32 t);
void LocalInterpComp_SetLocation(InterpComp* interp, LocationUpdate* update, bool interpolate);
void LocalInterpComp_AdvanceState(InterpComp* interp);
/* Entity component that performs interpolation for network players. */
typedef struct NetInterpComp_ {
InterpComp Base;
/* Last known position and orientation sent by the server. */
InterpState Cur;
Int32 StatesCount;
InterpState States[10];
} NetInterpComp;
void NetInterpComp_SetLocation(NetInterpComp* interp, LocationUpdate* update, bool interpolate);
void NetInterpComp_AdvanceState(NetInterpComp* interp);
#endif

View File

@ -104,6 +104,8 @@ Event_Real32 WorldEvents_MapLoading; /* Portion of world is decompressed/gener
Event_Void WorldEvents_MapLoaded; /* New world has finished loading, player can now interact with it. */
Event_Int32 WorldEvents_EnvVarChanged; /* World environment variable changed by player/CPE/WoM config. */
Event_Void ChatEvents_FontChanged; /* User changes whether system chat font used, and when the bitmapped font texture changes. */
/* Environment variable identifiers*/
typedef Int32 EnvVar;
#define EnvVar_EdgeBlock 0

View File

@ -14,9 +14,7 @@
*/
#define ICOUNT(verticesCount) (((verticesCount) >> 2) * 6)
/* Initalises this graphics API. */
void Gfx_Init(void);
/* Frees memory allocated by this graphics API. */
void Gfx_Free(void);
/* Maximum supported length of a dimension (width and height) of a 2D texture. */
@ -30,9 +28,7 @@ bool Gfx_Mipmaps;
/* Whether the backend supports setting the number of custom mipmaps levels. */
bool Gfx_CustomMipmapsLevels;
/* Maximum number of vertices that can be indexed. */
#define GFX_MAX_INDICES (65536 / 4 * 6)
/* Maximum number of vertices that can be indexed. */
#define GFX_MAX_VERTICES 65536
/* Callback invoked when the current context is lost, and is repeatedly invoked until the context can be retrieved. */
@ -44,78 +40,51 @@ GfxResourceID Gfx_CreateTexture(Bitmap* bmp, bool managedPool, bool mipmaps);
/* Updates the sub-rectangle (x, y) -> (x + part.Width, y + part.Height)
of the native texture associated with the given ID, with the pixels encapsulated in the 'part' instance. */
void Gfx_UpdateTexturePart(GfxResourceID texId, Int32 x, Int32 y, Bitmap* part, bool mipmaps);
/* Binds the given texture id so that it can be used for rasterization. */
void Gfx_BindTexture(GfxResourceID texId);
/* Frees all native resources held for the given texture id. */
void Gfx_DeleteTexture(GfxResourceID* texId);
/* Sets whether texturing is applied when rasterizing primitives. */
void Gfx_SetTexturing(bool enabled);
/* Enables mipmapping for subsequent texture drawing. */
void Gfx_EnableMipmaps(void);
/* Disbles mipmapping for subsequent texture drawing. */
void Gfx_DisableMipmaps(void);
/* Gets whether fog is currently enabled. */
bool Gfx_GetFog(void);
/* Sets whether fog is currently enabled. */
void Gfx_SetFog(bool enabled);
/* Sets the fog colour that is blended with final primitive colours. */
void Gfx_SetFogColour(PackedCol col);
/* Sets the density of exp and exp^2 fog */
void Gfx_SetFogDensity(Real32 value);
/* Sets the start radius of fog for linear fog. */
void Gfx_SetFogStart(Real32 value);
/* Sets the end radius of fog for for linear fog. */
void Gfx_SetFogEnd(Real32 value);
/* Sets the current fog mode. (linear, exp, or exp^2) */
void Gfx_SetFogMode(Fog fogMode);
void Gfx_SetFogMode(Int32 fogMode);
/* Whether back facing primitives should be culled by the 3D graphics api. */
void Gfx_SetFaceCulling(bool enabled);
/* Sets hether alpha testing is currently enabled. */
void Gfx_SetAlphaTest(bool enabled);
/* Sets the alpha test compare function that is used when alpha testing is enabled. */
void Gfx_SetAlphaTestFunc(CompareFunc compareFunc, Real32 refValue);
/* Whether alpha blending is currently enabled. */
void Gfx_SetAlphaTestFunc(Int32 compareFunc, Real32 refValue);
void Gfx_SetAlphaBlending(bool enabled);
/* Sets the alpha blend function that is used when alpha blending is enabled. */
void Gfx_SetAlphaBlendFunc(BlendFunc srcBlendFunc, BlendFunc dstBlendFunc);
void Gfx_SetAlphaBlendFunc(Int32 srcBlendFunc, Int32 dstBlendFunc);
/* Whether blending between the alpha components of the texture and colour are performed. */
void Gfx_SetAlphaArgBlend(bool enabled);
/* Clears the underlying back and/or front buffer. */
void Gfx_Clear(void);
/* Sets the colour the screen is cleared to when Clear() is called. */
void Gfx_ClearColour(PackedCol col);
/* Whether depth testing is currently enabled. */
void Gfx_SetDepthTest(bool enabled);
/* Sets the depth test compare function that is used when depth testing is enabled. */
void Gfx_SetDepthTestFunc(CompareFunc compareFunc);
/* Whether writing to the colour buffer is enabled. */
void Gfx_SetDepthTestFunc(Int32 compareFunc);
void Gfx_SetColourWrite(bool enabled);
/* Whether writing to the depth buffer is enabled. */
void Gfx_SetDepthWrite(bool enabled);
/* Creates a vertex buffer that can have its data dynamically updated. */
GfxResourceID Gfx_CreateDynamicVb(VertexFormat vertexFormat, Int32 maxVertices);
GfxResourceID Gfx_CreateDynamicVb(Int32 vertexFormat, Int32 maxVertices);
/* Creates a static vertex buffer that has its data set at creation,
but the vertex buffer's data cannot be updated after creation.*/
GfxResourceID Gfx_CreateVb(void* vertices, VertexFormat vertexFormat, Int32 count);
GfxResourceID Gfx_CreateVb(void* vertices, Int32 vertexFormat, Int32 count);
/* Creates a static index buffer that has its data set at creation,
but the index buffer's data cannot be updated after creation. */
GfxResourceID Gfx_CreateIb(void* indices, Int32 indicesCount);
/* Sets the currently active vertex buffer to the given id. */
void Gfx_BindVb(GfxResourceID vb);
/* Sets the currently active index buffer to the given id. */
void Gfx_BindIb(GfxResourceID ib);
/* Frees all native resources held for the vertex buffer associated with the given id. */
void Gfx_DeleteVb(GfxResourceID* vb);
/* Frees all native resources held for the index buffer associated with the given id. */
void Gfx_DeleteIb(GfxResourceID* ib);
/* Informs the graphics API that the format of the vertex data used in subsequent
draw calls will be in the given format. */
void Gfx_SetBatchFormat(VertexFormat vertexFormat);
void Gfx_SetBatchFormat(Int32 vertexFormat);
/* Binds and updates the data of the current dynamic vertex buffer's data.
This method also replaces the dynamic vertex buffer's data first with the given vertices before drawing. */
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, Int32 vCount);
@ -129,42 +98,25 @@ void Gfx_DrawVb_IndexedTris(Int32 verticesCount);
void Gfx_DrawIndexedVb_TrisT2fC4b(Int32 verticesCount, Int32 startVertex);
static Int32 Gfx_strideSizes[2] = { 16, 24 };
/* Sets the matrix type that load/push/pop operations should be applied to. */
void Gfx_SetMatrixMode(MatrixType matrixType);
/* Sets the current matrix to the given matrix.*/
void Gfx_SetMatrixMode(Int32 matrixType);
void Gfx_LoadMatrix(Matrix* matrix);
/* Sets the current matrix to the identity matrix. */
void Gfx_LoadIdentityMatrix(void);
/* Multiplies the current matrix by the given matrix, then
sets the current matrix to the result of the multiplication. */
void Gfx_MultiplyMatrix(Matrix* matrix);
/* Gets the top matrix the current matrix stack and pushes it to the stack. */
void Gfx_PushMatrix(void);
/* Removes the top matrix from the current matrix stack, then
sets the current matrix to the new top matrix of the stack. */
void Gfx_PopMatrix(void);
/* Loads an orthographic projection matrix for the given height.*/
void Gfx_LoadOrthoMatrix(Real32 width, Real32 height);
/*Outputs a .png screenshot of the backbuffer to the specified file. */
/* Outputs a .png screenshot of the backbuffer to the specified file. */
void Gfx_TakeScreenshot(STRING_PURE String* output, Int32 width, Int32 height);
/* Adds a warning to game's chat if this graphics API has problems with the current user's GPU.
Returns boolean of whether legacy rendering mode is needed. */
bool Gfx_WarnIfNecessary(void);
/* Informs the graphic api to update its state in preparation for a new frame. */
void Gfx_BeginFrame(void);
/* Informs the graphic api to update its state in preparation for the end of a frame,
and to prepare that frame for display on the monitor. */
void Gfx_EndFrame(void);
/* Sets whether the graphics api should tie frame rendering to the refresh rate of the monitor. */
void Gfx_SetVSync(bool value);
/* Raised when the dimensions of the game's window have changed. */
void Gfx_OnWindowResize(void);
/* Makes an array of strings of information about the graphics API. */
void Gfx_MakeApiInfo(void);
#define Gfx_ApiInfo_Count 32
/* Array of strings for information about the graphics API.
Max of Gfx_ApiInfo_Count strings, check if string is included by checking length > 0*/
#define Gfx_ApiInfo_Count 8
String Gfx_ApiInfo[Gfx_ApiInfo_Count];
#endif

View File

@ -2,12 +2,10 @@
#define CC_GFXENUMS_H
/* Vertex data format types*/
typedef Int32 VertexFormat;
#define VERTEX_FORMAT_P3FC4B 0
#define VERTEX_FORMAT_P3FT2FC4B 1
/* 3D graphics pixel comparison functions */
typedef Int32 CompareFunc;
#define COMPARE_FUNC_ALWAYS 0
#define COMPARE_FUNC_NOTEQUAL 1
#define COMPARE_FUNC_NEVER 2
@ -18,7 +16,6 @@ typedef Int32 CompareFunc;
#define COMPARE_FUNC_GREATER 7
/* 3D graphics pixel blending functions */
typedef Int32 BlendFunc;
#define BLEND_FUNC_ZERO 0
#define BLEND_FUNC_ONE 1
#define BLEND_FUNC_SRC_ALPHA 2
@ -27,13 +24,11 @@ typedef Int32 BlendFunc;
#define BLEND_FUNC_INV_DST_ALPHA 5
/* 3D graphics pixel fog blending functions */
typedef Int32 Fog;
#define FOG_LINEAR 0
#define FOG_EXP 1
#define FOG_EXP2 2
/* 3D graphics matrix types */
typedef Int32 MatrixType;
#define MATRIX_TYPE_PROJECTION 0
#define MATRIX_TYPE_MODELVIEW 1
#define MATRIX_TYPE_TEXTURE 2

View File

@ -58,8 +58,6 @@ typedef struct Screen_ {
bool RenderHUDOver;
/* Called when the game window is resized. */
void (*OnResize)(struct Screen_* screen);
void (*OnContextLost)(struct Screen_* screen);
void (*OnContextRecreated)(struct Screen_* screen);
} Screen;
void Screen_Reset(Screen* screen);

View File

@ -136,7 +136,7 @@ void Hotkeys_Init(void) {
if (hotkey == Key_Unknown || strText.length == 0 || !Convert_TryParseUInt8(&strFlags, &flags)
|| !Convert_TryParseBool(&strMoreInput, &moreInput)) { continue; }
Hotkeys_AddHotkey(hotkey, flags, &strText, moreInput);
Hotkeys_Add(hotkey, flags, &strText, moreInput);
}
}

View File

@ -9,7 +9,6 @@
/* Calculates the intersection points of a ray and a rotated bounding box. */
bool Intersection_RayIntersectsRotatedBox(Vector3 origin, Vector3 dir, Entity* target, Real32* tMin, Real32* tMax);
/* Calculates the intersection points of a ray and a bounding box.
Source: http://www.cs.utah.edu/~awilliam/box/box.pdf */
bool Intersection_RayIntersectsBox(Vector3 origin, Vector3 dir, Vector3 min, Vector3 max, Real32* t0, Real32* t1);

View File

@ -196,8 +196,8 @@ void Gfx_SetFogEnd(Real32 value) {
gl_lastFogEnd = value;
}
Fog gl_lastFogMode = -1;
void Gfx_SetFogMode(Fog mode) {
Int32 gl_lastFogMode = -1;
void Gfx_SetFogMode(Int32 mode) {
if (mode == gl_lastFogMode) return;
glFogi(GL_FOG_MODE, gl_fogModes[mode]);
gl_lastFogMode = mode;
@ -206,12 +206,12 @@ void Gfx_SetFogMode(Fog mode) {
void Gfx_SetFaceCulling(bool enabled) { GL_TOGGLE(GL_CULL_FACE); }
void Gfx_SetAlphaTest(bool enabled) { GL_TOGGLE(GL_ALPHA_TEST); }
void Gfx_SetAlphaTestFunc(CompareFunc func, Real32 value) {
void Gfx_SetAlphaTestFunc(Int32 func, Real32 value) {
glAlphaFunc(gl_compare[func], value);
}
void Gfx_SetAlphaBlending(bool enabled) { GL_TOGGLE(GL_BLEND); }
void Gfx_SetAlphaBlendFunc(BlendFunc srcFunc, BlendFunc dstFunc) {
void Gfx_SetAlphaBlendFunc(Int32 srcFunc, Int32 dstFunc) {
glBlendFunc(gl_blend[srcFunc], gl_blend[dstFunc]);
}
void Gfx_SetAlphaArgBlend(bool enabled) { }
@ -237,7 +237,7 @@ void Gfx_SetDepthWrite(bool enabled) {
}
void Gfx_SetDepthTest(bool enabled) { GL_TOGGLE(GL_DEPTH_TEST); }
void Gfx_SetDepthTestFunc(CompareFunc compareFunc) {
void Gfx_SetDepthTestFunc(Int32 compareFunc) {
glDepthFunc(gl_compare[compareFunc]);
}
@ -249,7 +249,7 @@ GfxResourceID GL_GenAndBind(GLenum target) {
return id;
}
GfxResourceID Gfx_CreateDynamicVb(VertexFormat vertexFormat, Int32 maxVertices) {
GfxResourceID Gfx_CreateDynamicVb(Int32 vertexFormat, Int32 maxVertices) {
if (gl_lists) return gl_DYNAMICLISTID;
Int32 id = GL_GenAndBind(GL_ARRAY_BUFFER);
UInt32 sizeInBytes = maxVertices * Gfx_strideSizes[vertexFormat];
@ -258,7 +258,7 @@ GfxResourceID Gfx_CreateDynamicVb(VertexFormat vertexFormat, Int32 maxVertices)
}
#define gl_MAXINDICES ICOUNT(65536)
GfxResourceID Gfx_CreateVb(void* vertices, VertexFormat vertexFormat, Int32 count) {
GfxResourceID Gfx_CreateVb(void* vertices, Int32 vertexFormat, Int32 count) {
if (gl_lists) {
Int32 list = glGenLists(1);
glNewList(list, GL_COMPILE);
@ -328,7 +328,7 @@ typedef void (*GL_SetupVBRangeFunc)(Int32 startVertex);
GL_SetupVBFunc gl_setupVBFunc;
GL_SetupVBRangeFunc gl_setupVBRangeFunc;
Int32 gl_batchStride;
VertexFormat gl_batchFormat = -1;
Int32 gl_batchFormat = -1;
void GL_SetupVbPos3fCol4b(void) {
glVertexPointer(3, GL_FLOAT, VertexP3fC4b_Size, (void*)0);
@ -354,7 +354,7 @@ void GL_SetupVbPos3fTex2fCol4b_Range(Int32 startVertex) {
glTexCoordPointer(2, GL_FLOAT, VertexP3fT2fC4b_Size, (void*)(offset + 16));
}
void Gfx_SetBatchFormat(VertexFormat vertexFormat) {
void Gfx_SetBatchFormat(Int32 vertexFormat) {
if (vertexFormat == gl_batchFormat) return;
if (gl_batchFormat == VERTEX_FORMAT_P3FT2FC4B) {
@ -480,8 +480,8 @@ void Gfx_DrawIndexedVb_TrisT2fC4b(Int32 verticesCount, Int32 startVertex) {
}
MatrixType gl_lastMatrixType = 0;
void Gfx_SetMatrixMode(MatrixType matrixType) {
Int32 gl_lastMatrixType = 0;
void Gfx_SetMatrixMode(Int32 matrixType) {
if (matrixType == gl_lastMatrixType) return;
glMatrixMode(gl_matrixModes[matrixType]);
gl_lastMatrixType = matrixType;

View File

@ -102,8 +102,8 @@ Int32 Options_Insert(STRING_PURE String* key, STRING_PURE String* value) {
}
}
StringsBuffer_Add(&Options_Keys, &key);
StringsBuffer_Add(&Options_Values, &value);
StringsBuffer_Add(&Options_Keys, key);
StringsBuffer_Add(&Options_Values, value);
return Options_Keys.Count;
}

View File

@ -129,7 +129,7 @@ void InventoryScreen_Init(GuiElement* elem) {
TableWidget_Create(&screen->Table);
screen->Table.Font = screen->Font;
screen->Table.ElementsPerRow = Game_PureClassic ? 9 : 10;
elem->Init(&elem);
elem->Init(elem);
Key_KeyRepeat = true;
Event_RegisterVoid(&BlockEvents_PermissionsChanged, InventoryScreen_OnBlockChanged);
@ -154,7 +154,7 @@ void InventoryScreen_Free(GuiElement* elem) {
InventoryScreen* screen = (InventoryScreen*)elem;
Platform_FreeFont(&screen->Font);
elem = &screen->Table.Base.Base;
elem->Free(&elem);
elem->Free(elem);
Key_KeyRepeat = false;
Event_UnregisterVoid(&BlockEvents_PermissionsChanged, InventoryScreen_OnBlockChanged);
@ -166,9 +166,10 @@ void InventoryScreen_Free(GuiElement* elem) {
bool InventoryScreen_HandlesKeyDown(GuiElement* elem, Key key) {
InventoryScreen* screen = (InventoryScreen*)elem;
TableWidget* table = &screen->Table;
GuiElement* elem = &screen->Table.Base.Base;
elem = &screen->Table.Base.Base;
if (key == KeyBind_Get(KeyBind_PauseOrExit)) {
gGui_SetNewScreen(NULL);
Gui_SetNewScreen(NULL);
} else if (key == KeyBind_Get(KeyBind_Inventory) && screen->ReleasedInv) {
Gui_SetNewScreen(NULL);
} else if (key == Key_Enter && table->SelectedIndex != -1) {
@ -192,7 +193,7 @@ bool InventoryScreen_HandlesKeyUp(GuiElement* elem, Key key) {
bool InventoryScreen_HandlesMouseDown(GuiElement* elem, Int32 x, Int32 y, MouseButton btn) {
InventoryScreen* screen = (InventoryScreen*)elem;
TableWidget* table = &screen->Table;
GuiElement* elem = &screen->Table.Base.Base;
elem = &screen->Table.Base.Base;
if (table->Scroll.DraggingMouse || game.Gui.hudScreen.hotbar.HandlesMouseDown(x, y, btn))
return true;
@ -225,7 +226,7 @@ bool InventoryScreen_HandlesMouseScroll(GuiElement* elem, Real32 delta) {
return elem->HandlesMouseScroll(elem, delta);
}
Screen* InventoryScreen_GetInstance(void) {
Screen* InventoryScreen_MakeInstance(void) {
InventoryScreen* screen = &InventoryScreen_Instance;
Platform_MemSet(&screen, 0, sizeof(InventoryScreen));
Screen_Reset(&screen->Base);
@ -237,13 +238,10 @@ Screen* InventoryScreen_GetInstance(void) {
screen->Base.Base.HandlesMouseMove = InventoryScreen_HandlesMouseMove;
screen->Base.Base.HandlesMouseScroll = InventoryScreen_HandlesMouseScroll;
screen->Base.OnContextLost = InventoryScreen_ContextLost;
screen->Base.OnContextRecreated = InventoryScreen_ContextRecreated;
screen->Base.OnResize = InventoryScreen_OnResize;
screen->Base.Base.Init = InventoryScreen_Init;
screen->Base.Base.Render = InventoryScreen_Render;
screen->Base.Base.Free = InventoryScreen_Free;
return &screen->Base;
}
extern Screen* InventoryScreen_Unsafe_RawPointer = &InventoryScreen_Instance.Base;
extern Screen* InventoryScreen_UNSAFE_RawPointer = &InventoryScreen_Instance.Base;

View File

@ -16,8 +16,8 @@ typedef struct ClickableScreen_ {
} ClickableScreen;
void ClickableScreen_Create(ClickableScreen* screen);
Screen* InventoryScreen_GetInstance(void);
Screen* InventoryScreen_MakeInstance(void);
/* Raw pointer to inventory screen. DO NOT USE THIS. Use InventoryScreen_GetInstance() */
extern Screen* InventoryScreen_Unsafe_RawPointer;
/* Raw pointer to inventory screen. DO NOT USE THIS. Use InventoryScreen_MakeInstance() */
extern Screen* InventoryScreen_UNSAFE_RawPointer;
#endif

View File

@ -440,7 +440,7 @@ bool HotbarWidget_HandlesMouseDown(GuiElement* elem, Int32 x, Int32 y, MouseButt
Widget* w = (Widget*)elem;
if (btn != MouseButton_Left || !Gui_Contains(w->X, w->Y, w->Width, w->Height, x, y)) return false;
Screen* screen = Gui_GetActiveScreen();
if (screen != InventoryScreen_Unsafe_RawPointer) return false;
if (screen != InventoryScreen_UNSAFE_RawPointer) return false;
HotbarWidget* widget = (HotbarWidget*)elem;
Int32 width = (Int32)(widget->ElemSize * widget->BorderSize);