Port more of Entity to C.

This commit is contained in:
UnknownShadow200 2017-09-16 20:14:20 +10:00
parent e798f0f7ac
commit 39aa37a83d
16 changed files with 150 additions and 95 deletions

View File

@ -285,7 +285,7 @@ namespace ClassicalSharp.Entities {
public void DoEntityPush() {
for (int id = 0; id < EntityList.MaxCount; id++) {
Entity other = game.Entities[id];
Entity other = game.Entities.List[id];
if (other == null || other == entity) continue;
if (other.Model is BlockModel) continue; // block models shouldn't push you

View File

@ -38,8 +38,6 @@ namespace ClassicalSharp.Entities {
/// <summary> Returns the size of the model that is used for collision detection. </summary>
public Vector3 Size;
public byte ID;
public int TextureId = -1, MobTextureId = -1;
public short Health = 10;
@ -57,7 +55,7 @@ namespace ClassicalSharp.Entities {
public SkinType SkinType;
public AnimatedComponent anim;
public float uScale = 1, vScale = 1;
public bool NoShade = false;
public bool NoShade;
/// <summary> Rotation of the entity's head horizontally. (i.e. looking north or east) </summary>

View File

@ -16,7 +16,7 @@ namespace ClassicalSharp.Entities {
public const int MaxCount = 256;
public const byte SelfID = 255;
public Entity[] Entities = new Entity[MaxCount];
public Entity[] List = new Entity[MaxCount];
public Game game;
public EntityShadow ShadowMode = EntityShadow.None;
byte closestId;
@ -39,9 +39,9 @@ namespace ClassicalSharp.Entities {
/// <summary> Performs a tick call for all player entities contained in this list. </summary>
public void Tick(ScheduledTask task) {
for (int i = 0; i < Entities.Length; i++) {
if (Entities[i] == null) continue;
Entities[i].Tick(task.Interval);
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
List[i].Tick(task.Interval);
}
}
@ -49,9 +49,9 @@ namespace ClassicalSharp.Entities {
public void RenderModels(IGraphicsApi gfx, double delta, float t) {
gfx.Texturing = true;
gfx.AlphaTest = true;
for (int i = 0; i < Entities.Length; i++) {
if (Entities[i] == null) continue;
Entities[i].RenderModel(delta, t);
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
List[i].RenderModel(delta, t);
}
gfx.Texturing = false;
gfx.AlphaTest = false;
@ -70,10 +70,10 @@ namespace ClassicalSharp.Entities {
hadFog = gfx.Fog;
if (hadFog) gfx.Fog = false;
for (int i = 0; i < Entities.Length; i++) {
if (Entities[i] == null) continue;
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
if (i != closestId || i == SelfID)
Entities[i].RenderName();
List[i].RenderName();
}
gfx.Texturing = false;
@ -90,10 +90,10 @@ namespace ClassicalSharp.Entities {
bool allNames = !(NamesMode == NameMode.Hovered || NamesMode == NameMode.All)
&& game.LocalPlayer.Hacks.CanSeeAllNames;
for (int i = 0; i < Entities.Length; i++) {
for (int i = 0; i < List.Length; i++) {
bool hover = (i == closestId || allNames) && i != SelfID;
if (Entities[i] != null && hover)
Entities[i].RenderName();
if (List[i] != null && hover)
List[i].RenderName();
}
gfx.Texturing = false;
@ -103,37 +103,37 @@ namespace ClassicalSharp.Entities {
}
void ContextLost() {
for (int i = 0; i < Entities.Length; i++) {
if (Entities[i] == null) continue;
Entities[i].ContextLost();
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
List[i].ContextLost();
}
}
void ContextRecreated() {
for (int i = 0; i < Entities.Length; i++) {
if (Entities[i] == null) continue;
Entities[i].ContextRecreated();
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
List[i].ContextRecreated();
}
}
void ChatFontChanged(object sender, EventArgs e) {
for (int i = 0; i < Entities.Length; i++) {
if (Entities[i] == null) continue;
Player p = Entities[i] as Player;
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
Player p = List[i] as Player;
if (p != null) p.UpdateName();
}
}
public void RemoveEntity(byte id) {
game.EntityEvents.RaiseRemoved(id);
Entities[id].Despawn();
Entities[id] = null;
List[id].Despawn();
List[id] = null;
}
/// <summary> Disposes of all player entities contained in this list. </summary>
public void Dispose() {
for (int i = 0; i < Entities.Length; i++) {
if (Entities[i] == null) continue;
for (int i = 0; i < List.Length; i++) {
if (List[i] == null) continue;
RemoveEntity((byte)i);
}
@ -151,8 +151,8 @@ namespace ClassicalSharp.Entities {
float closestDist = float.PositiveInfinity;
byte targetId = SelfID;
for (int i = 0; i < Entities.Length - 1; i++) { // -1 because we don't want to pick against local player
Entity p = Entities[i];
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;
@ -164,16 +164,6 @@ namespace ClassicalSharp.Entities {
return targetId;
}
/// <summary> Gets or sets the player entity for the specified id. </summary>
public Entity this[int id] {
get { return Entities[id]; }
set {
Entities[id] = value;
if (value != null)
value.ID = (byte)id;
}
}
public void DrawShadows() {
if (ShadowMode == EntityShadow.None) return;
ShadowComponent.boundShadowTex = false;
@ -185,7 +175,7 @@ namespace ClassicalSharp.Entities {
gfx.Texturing = true;
gfx.SetBatchFormat(VertexFormat.P3fT2fC4b);
ShadowComponent.Draw(game, Entities[SelfID]);
ShadowComponent.Draw(game, List[SelfID]);
if (ShadowMode == EntityShadow.CircleAll)
DrawOtherShadows();
@ -197,8 +187,8 @@ namespace ClassicalSharp.Entities {
void DrawOtherShadows() {
for (int i = 0; i < SelfID; i++) {
if (Entities[i] == null) continue;
Player p = Entities[i] as Player;
if (List[i] == null) continue;
Player p = List[i] as Player;
if (p != null) ShadowComponent.Draw(game, p);
}
}

View File

@ -8,7 +8,7 @@ namespace ClassicalSharp.Entities {
public sealed class NetPlayer : Player {
NetInterpComponent interp;
public NetPlayer(string displayName, string skinName, Game game, byte id) : base(game) {
public NetPlayer(string displayName, string skinName, Game game) : base(game) {
DisplayName = displayName;
SkinName = skinName;
interp = new NetInterpComponent(game, this);

View File

@ -141,18 +141,20 @@ namespace ClassicalSharp.Entities {
}
Player FirstOtherWithSameSkin() {
Entity[] entities = game.Entities.List;
for (int i = 0; i < EntityList.MaxCount; i++) {
if (game.Entities[i] == null || game.Entities[i] == this) continue;
Player p = game.Entities[i] as Player;
if (entities[i] == null || entities[i] == this) continue;
Player p = entities[i] as Player;
if (p != null && p.SkinName == SkinName) return p;
}
return null;
}
Player FirstOtherWithSameSkinAndFetchedSkin() {
Entity[] entities = game.Entities.List;
for (int i = 0; i < EntityList.MaxCount; i++) {
if (game.Entities[i] == null || game.Entities[i] == this) continue;
Player p = game.Entities[i] as Player;
if (entities[i] == null || entities[i] == this) continue;
Player p = entities[i] as Player;
if (p != null && p.SkinName == SkinName && p.fetchedSkin) return p;
}
return null;
@ -160,9 +162,10 @@ namespace ClassicalSharp.Entities {
// Apply or reset skin, for all players with same skin
void SetSkinAll(bool reset) {
Entity[] entities = game.Entities.List;
for (int i = 0; i < EntityList.MaxCount; i++) {
if (game.Entities[i] == null) continue;
Player p = game.Entities[i] as Player;
if (entities[i] == null) continue;
Player p = entities[i] as Player;
if (p == null || p.SkinName != SkinName) continue;
if (reset) { p.ResetSkin(); }

View File

@ -87,7 +87,7 @@ namespace ClassicalSharp {
BlockInfo.SetDefaultPerms();
World = new World(this);
LocalPlayer = AddComponent(new LocalPlayer(this));
Entities[EntityList.SelfID] = LocalPlayer;
Entities.List[EntityList.SelfID] = LocalPlayer;
Width = window.Width; Height = window.Height;
MapRenderer = new MapRenderer(this);

View File

@ -360,9 +360,10 @@ namespace ClassicalSharp {
if (DefaultPlayerSkinType == SkinType.Invalid)
throw new NotSupportedException("char.png has invalid dimensions");
Entity[] entities = Entities.List;
for (int i = 0; i < EntityList.MaxCount; i++) {
if (Entities[i] == null || Entities[i].TextureId != -1) continue;
Entities[i].SkinType = DefaultPlayerSkinType;
if (entities[i] == null || entities[i].TextureId != -1) continue;
entities[i].SkinType = DefaultPlayerSkinType;
}
}

View File

@ -144,7 +144,7 @@ namespace ClassicalSharp {
pos + BlockInfo.MaxBB[block]);
for (int id = 0; id < EntityList.SelfID; id++) {
Entity entity = game.Entities[id];
Entity entity = game.Entities.List[id];
if (entity == null) continue;
AABB bounds = entity.Bounds;

View File

@ -200,13 +200,11 @@ namespace ClassicalSharp.GraphicsAPI {
}
internal int MipmapsLevels(int width, int height) {
int lvlsWidth = Utils.Log2(width), lvlsHeight = Utils.Log2(height);
if (CustomMipmapsLevels) {
int lvls = Math.Min(lvlsWidth, lvlsHeight);
return Math.Min(lvls, 4);
} else {
return Math.Max(lvlsWidth, lvlsHeight);
}
int lvlsWidth = Utils.Log2(width), lvlsHeight = Utils.Log2(height);
int lvls = Math.Min(lvlsWidth, lvlsHeight);
if (lvls > 4 && CustomMipmapsLevels) lvls = 4;
return lvls;
}
}

View File

@ -78,7 +78,7 @@ namespace ClassicalSharp.Mode {
}
bool PickEntity(byte id) {
Entity entity = game.Entities[id];
Entity entity = game.Entities.List[id];
LocalPlayer p = game.LocalPlayer;
Vector3 delta = p.Position - entity.Position;
@ -162,7 +162,7 @@ namespace ClassicalSharp.Mode {
Vector3 pos = Respawn.FindSpawnPosition(game, x, z, fail.Size);
fail.SetLocation(LocationUpdate.MakePos(pos, false), false);
game.Entities[i] = fail;
game.Entities.List[i] = fail;
}
}

View File

@ -42,10 +42,10 @@ namespace ClassicalSharp.Network {
internal void AddEntity(byte id, string displayName, string skinName, bool readPosition) {
if (id != EntityList.SelfID) {
Entity oldEntity = game.Entities[id];
Entity oldEntity = game.Entities.List[id];
if (oldEntity != null) game.Entities.RemoveEntity(id);
game.Entities[id] = new NetPlayer(displayName, skinName, game, id);
game.Entities.List[id] = new NetPlayer(displayName, skinName, game);
game.EntityEvents.RaiseAdded(id);
} else {
game.LocalPlayer.Despawn();
@ -70,7 +70,7 @@ namespace ClassicalSharp.Network {
}
internal void RemoveEntity(byte id) {
Entity entity = game.Entities[id];
Entity entity = game.Entities.List[id];
if (entity == null) return;
if (id != EntityList.SelfID) game.Entities.RemoveEntity(id);
@ -83,7 +83,7 @@ namespace ClassicalSharp.Network {
}
internal void UpdateLocation(byte playerId, LocationUpdate update, bool interpolate) {
Entity entity = game.Entities[playerId];
Entity entity = game.Entities.List[playerId];
if (entity != null) {
entity.SetLocation(update, interpolate);
}

View File

@ -223,9 +223,9 @@ namespace ClassicalSharp.Network.Protocols {
}
void HandleChangeModel() {
byte playerId = reader.ReadUInt8();
byte id = reader.ReadUInt8();
string modelName = Utils.ToLower(reader.ReadString());
Entity entity = game.Entities[playerId];
Entity entity = game.Entities.List[id];
if (entity != null) entity.SetModel(modelName);
}
@ -368,7 +368,7 @@ namespace ClassicalSharp.Network.Protocols {
byte type = reader.ReadUInt8();
int value = reader.ReadInt32();
Entity entity = game.Entities[id];
Entity entity = game.Entities.List[id];
if (entity == null) return;
LocationUpdate update = LocationUpdate.Empty();

View File

@ -8,6 +8,7 @@
#include "Camera.h"
#include "Platform.h"
#include "Funcs.h"
#include "ModelCache.h"
Real32 LocationUpdate_Clamp(Real32 degrees) {
degrees = Math_Mod(degrees, 360.0f);
@ -26,7 +27,7 @@ void LocationUpdate_Construct(LocationUpdate* update, Real32 x, Real32 y, Real32
update->RelativePosition = relPos;
}
#define exc LocationUpdate_Excluded
#define exc LOCATIONUPDATE_EXCLUDED
void LocationUpdate_Empty(LocationUpdate* update) {
LocationUpdate_Construct(update, 0.0f, 0.0f, 0.0f, exc, exc, exc, exc, false, false);
}
@ -44,6 +45,16 @@ void LocationUpdate_MakePosAndOri(LocationUpdate* update, Vector3 pos, Real32 ro
}
void Entity_Init(Entity* entity) {
entity->ModelScale = Vector3_Create1(1.0f);
entity->TextureId = -1;
entity->MobTextureId = -1;
entity->uScale = 1.0f;
entity->vScale = 1.0f;
UInt8* ptr = entity->ModelNameBuffer;
entity->ModelName = String_FromRawBuffer(ptr, ENTITY_MAX_MODEL_LENGTH);
}
Vector3 Entity_GetEyePosition(Entity* entity) {
Vector3 pos = entity->Position;
pos.Y += entity->Model->GetEyeY(entity) * entity->ModelScale.Y;
@ -76,6 +87,61 @@ void Entity_GetBounds(Entity* entity, AABB* bb) {
AABB_Make(bb, &entity->Position, &entity->Size);
}
void Entity_ParseScale(Entity* entity, String scale) {
if (scale.buffer == NULL) return;
Real32 value;
if (!Convert_TryParseReal32(&scale, &value)) return;
Real32 maxScale = entity->Model->MaxScale;
Math_Clamp(value, 0.01f, maxScale);
entity->ModelScale = Vector3_Create1(value);
}
void Entity_SetModel(Entity* entity, String* model) {
entity->ModelScale = Vector3_Create1(1.0f);
entity->ModelBlock = BlockID_Air;
String_Clear(&entity->ModelName);
Int32 sep = String_IndexOf(model, '|', 0);
String name, scale;
if (sep == -1) {
name = *model;
scale = String_MakeNull();
} else {
name = String_UNSAFE_SubstringAt(model, sep + 1);
scale = String_UNSAFE_Substring(model, 0, sep);
}
/* 'giant' model kept for backwards compatibility */
String giant = String_FromConstant("giant");
if (String_CaselessEquals(model, &giant)) {
String_AppendConstant(&entity->ModelName, "humanoid");
entity->ModelScale = Vector3_Create1(2.0f);
} else if (Convert_TryParseUInt8(model, &entity->ModelBlock)) {
String_AppendConstant(&entity->ModelName, "block");
} else {
String_AppendString(&entity->ModelName, &name);
}
entity->Model = ModelCache_Get(&entity->ModelName);
Entity_ParseScale(entity, scale);
entity->MobTextureId = -1;
entity->Model->RecalcProperties(entity);
Entity_UpdateModelBounds(entity);
}
void Entity_UpdateModelBounds(Entity* entity) {
IModel* model = entity->Model;
Vector3 baseSize = model->GetCollisionSize();
Vector3_Multiply3(&entity->Size, &baseSize, &entity->ModelScale);
AABB* bb = &entity->ModelAABB;
model->GetPickingBounds(bb);
Vector3_Multiply3(&bb->Min, &bb->Min, &entity->ModelScale);
Vector3_Multiply3(&bb->Max, &bb->Max, &entity->ModelScale);
}
bool Entity_TouchesAny(AABB* bounds, TouchesAny_Condition condition) {
Vector3I bbMin, bbMax;
Vector3I_Floor(&bbMin, &bounds->Min);
@ -445,7 +511,7 @@ void InterpComp_SetPos(InterpState* state, LocationUpdate* update) {
}
Real32 NetInterpComp_Next(Real32 next, Real32 cur) {
if (next == LocationUpdate_Excluded) return cur;
if (next == LOCATIONUPDATE_EXCLUDED) return cur;
return next;
}
@ -508,7 +574,7 @@ void NetInterpComp_AdvanceState(NetInterpComp* interp) {
}
Real32 LocalInterpComp_Next(Real32 next, Real32 cur, Real32* last, bool interpolate) {
if (next == LocationUpdate_Excluded) return cur;
if (next == LOCATIONUPDATE_EXCLUDED) return cur;
if (!interpolate) *last = next;
return next;
}
@ -521,8 +587,8 @@ void LocalInterpComp_SetLocation(InterpComp* interp, LocationUpdate* update, boo
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 (blockOffset < ENTITY_ADJUSTMENT) {
next->Pos.Y += ENTITY_ADJUSTMENT;
}
if (!interpolate) {
prev->Pos = next->Pos;
@ -535,7 +601,7 @@ void LocalInterpComp_SetLocation(InterpComp* interp, LocationUpdate* update, boo
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 (update->RotY != LOCATIONUPDATE_EXCLUDED) {
if (!interpolate) {
interp->NextRotY = update->RotY;
entity->RotY = update->RotY;

View File

@ -11,11 +11,12 @@
*/
typedef struct IModel_ IModel; /* Forward declaration */
/* Constant offset used to avoid floating point roundoff errors. */
#define Entity_Adjustment 0.001f
/* Constant value specifying an angle is not included in an orientation update. */
#define LocationUpdate_Excluded -100000.31415926535f
/* Offset used to avoid floating point roundoff errors. */
#define ENTITY_ADJUSTMENT 0.001f
/* Special value specifying an angle is not included in an orientation update. */
#define LOCATIONUPDATE_EXCLUDED -100000.31415926535f
/* Maxmimum number of characters in a model name. */
#define ENTITY_MAX_MODEL_LENGTH 10
typedef bool (*TouchesAny_Condition)(BlockID block);
@ -24,7 +25,7 @@ This can be a relative position, full position, and/or an orientation update. */
typedef struct LocationUpdate_ {
/* Position of the update (if included). */
Vector3 Pos;
/* Orientation of the update (if included). If not, has the value of LocationUpdate_Excluded. */
/* Orientation of the update (if included). If not, has the value of LOCATIONUPDATE_EXCLUDED. */
Real32 RotX, RotY, RotZ, HeadX;
/* Whether this update includes an absolute or relative position. */
bool IncludesPosition;
@ -88,6 +89,7 @@ typedef struct Entity_ {
/* The model of this entity. (used for collision detection and rendering) */
IModel* Model;
UInt8 ModelNameBuffer[String_BufferSize(ENTITY_MAX_MODEL_LENGTH)];
/* The name of the model of this entity. Is "block" for all block ID models. */
String ModelName;
/* BlockID, if model name was originally a vaid block id. Avoids needing to repeatedly parse ModelName as a byte. */
@ -114,28 +116,23 @@ typedef struct Entity_ {
/* Initalises the given entity. */
void Entity_Init(Entity* entity);
/* Gets the position of the player's eye in the world. */
Vector3 Entity_GetEyePosition(Entity* entity);
/* Calculates the transformation matrix for the given entity. */
void Entity_GetTransform(Entity* entity, Vector3 pos, Vector3 scale);
/* Returns the bounding box that contains the model, without any rotations applied. */
void Entity_GetPickingBounds(Entity* entity, AABB* bb);
/* Bounding box of the model that collision detection is performed with, in world coordinates. */
void Entity_GetBounds(Entity* entity, AABB* bb);
/* Sets the model associated with this entity. ('name' or 'name|scale') */
void Entity_SetModel(Entity* entity, String* model);
void Entity_UpdateModelBounds(Entity* entity);
/* Determines whether any of the blocks that intersect the given bounding box satisfy the given condition. */
bool Entity_TouchesAny(AABB* bb, TouchesAny_Condition condition);
/* Determines whether any of the blocks that intersect the AABB of this entity are rope. */
bool Entity_TouchesAnyRope(Entity* entity);
bool Entity_TouchesAnyRope(Entity* entity);
/* Determines whether any of the blocks that intersect the AABB of this entity are lava or still lava. */
bool Entity_TouchesAnyLava(Entity* entity);
/* Determines whether any of the blocks that intersect the AABB of this entity are water or still water. */
bool Entity_TouchesAnyWater(Entity* entity);

View File

@ -214,5 +214,7 @@ void GfxCommon_GenMipmaps(Int32 width, Int32 height, UInt8* lvlScan0, UInt8* sca
Int32 GfxCommon_MipmapsLevels(Int32 width, Int32 height) {
Int32 lvlsWidth = Math_Log2(width), lvlsHeight = Math_Log2(height);
Int32 lvls = min(lvlsWidth, lvlsHeight);
return min(lvls, 4);
if (lvls > 4 && Gfx_CustomMipmapsLevels) lvls = 4;
return lvls;
}

View File

@ -38,7 +38,7 @@ Real32 Respawn_HighestFreeY(AABB* bb) {
Vector3 Respawn_FindSpawnPosition(Real32 x, Real32 z, Vector3 modelSize) {
Vector3 spawn = Vector3_Create3(x, 0.0f, z);
spawn.Y = World_Height + Entity_Adjustment;
spawn.Y = World_Height + ENTITY_ADJUSTMENT;
AABB bb;
AABB_Make(&bb, &spawn, &modelSize);
spawn.Y = 0.0f;