Now some entities spawn and can be clicked on.

This commit is contained in:
UnknownShadow200 2017-01-20 13:08:28 +11:00
parent 530e9eb09c
commit fd454c0c01
15 changed files with 184 additions and 98 deletions

View File

@ -150,13 +150,14 @@
<Compile Include="Blocks\BlockInfo.Atlas.cs" />
<Compile Include="Blocks\DefaultSet.cs" />
<Compile Include="Commands\SinglePlayerCommands.cs" />
<Compile Include="Entities\AI\AI.cs" />
<Compile Include="Entities\AI\FleeAI.cs" />
<Compile Include="Entities\AI\HostileAI.cs" />
<Compile Include="Entities\Components\LocalInterpComponent.cs" />
<Compile Include="Entities\Mobs\AI\AI.cs" />
<Compile Include="Entities\Mobs\AI\FleeAI.cs" />
<Compile Include="Entities\Mobs\AI\HostileAI.cs" />
<Compile Include="Entities\Components\AnimatedComponent.cs" />
<Compile Include="Entities\Components\HacksComponent.cs" />
<Compile Include="Entities\Components\InputComponent.cs" />
<Compile Include="Entities\Components\InterpolatedComponent.cs" />
<Compile Include="Entities\Components\NetInterpComponent.cs" />
<Compile Include="Entities\Components\CollisionsComponent.cs" />
<Compile Include="Entities\Components\NewCollisionsComponent.cs" />
<Compile Include="Entities\Components\PhysicsComponent.cs" />
@ -167,6 +168,7 @@
<Compile Include="Entities\EntityList.cs" />
<Compile Include="Entities\LocalPlayer.cs" />
<Compile Include="Entities\LocationUpdate.cs" />
<Compile Include="Entities\Mobs\MobEntity.cs" />
<Compile Include="Entities\NetPlayer.cs" />
<Compile Include="Entities\TabList.cs" />
<Compile Include="Events\EntityEvents.cs" />
@ -341,8 +343,9 @@
<Folder Include="2D\Widgets\Chat" />
<Folder Include="2D\Widgets\PlayerList" />
<Folder Include="Blocks" />
<Folder Include="Entities\AI" />
<Folder Include="Entities\Mobs\AI" />
<Folder Include="Entities\Components" />
<Folder Include="Entities\Mobs" />
<Folder Include="Events" />
<Folder Include="Generator" />
<Folder Include="Map\Lighting" />

View File

@ -0,0 +1,71 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using ClassicalSharp.Renderers;
using OpenTK;
namespace ClassicalSharp.Entities {
/// <summary> Entity component that performs interpolation of position and model head yaw over time. </summary>
public sealed class LocalInterpComponent {
Entity entity;
public LocalInterpComponent(Game game, Entity entity) {
this.entity = entity;
}
internal Vector3 lastPos, nextPos;
internal float lastHeadYaw, nextHeadYaw, lastPitch, nextPitch, lastYaw, nextYaw;
int yawStateCount;
float[] yawStates = new float[15];
public void SetLocation(LocationUpdate update, bool interpolate) {
if (update.IncludesPosition) {
nextPos = update.RelativePosition ? nextPos + update.Pos : update.Pos;
double blockOffset = nextPos.Y - Math.Floor(nextPos.Y);
if (blockOffset < Entity.Adjustment)
nextPos.Y += Entity.Adjustment;
if (!interpolate) {
lastPos = entity.Position = nextPos;
}
}
if (update.IncludesOrientation) {
nextHeadYaw = update.Yaw;
nextPitch = update.Pitch;
if (!interpolate) {
lastHeadYaw = entity.YawDegrees = nextHeadYaw;
lastPitch = entity.PitchDegrees = nextPitch;
entity.HeadYawDegrees = entity.YawDegrees;
yawStateCount = 0;
} else {
for (int i = 0; i < 3; i++)
AddYaw(Utils.LerpAngle(lastHeadYaw, nextHeadYaw, (i + 1) / 3f));
}
}
}
public void AdvanceState() {
lastPos = entity.Position = nextPos;
lastHeadYaw = nextHeadYaw;
lastYaw = nextYaw;
lastPitch = nextPitch;
if (yawStateCount > 0) {
nextYaw = yawStates[0];
RemoveOldest(yawStates, ref yawStateCount);
}
}
void AddYaw(float state) {
if (yawStateCount == yawStates.Length)
RemoveOldest(yawStates, ref yawStateCount);
yawStates[yawStateCount++] = state;
}
void RemoveOldest<T>(T[] array, ref int count) {
for (int i = 0; i < array.Length - 1; i++)
array[i] = array[i + 1];
count--;
}
}
}

View File

@ -6,10 +6,10 @@ using OpenTK;
namespace ClassicalSharp.Entities {
/// <summary> Entity component that performs interpolation of position and model head yaw over time. </summary>
public sealed class InterpolatedComponent {
public sealed class NetInterpComponent {
Entity entity;
public InterpolatedComponent(Game game, Entity entity) {
public NetInterpComponent(Game game, Entity entity) {
this.entity = entity;
}

View File

@ -22,7 +22,7 @@ namespace ClassicalSharp.Entities {
Vector3 lastSoundPos;
public void Tick(bool wasOnGround) {
Vector3 soundPos = p.nextPos;
Vector3 soundPos = p.interp.nextPos;
GetSound();
if (!anyNonAir) soundPos = Utils.MaxPos();
@ -55,7 +55,7 @@ namespace ClassicalSharp.Entities {
bool anyNonAir = false;
SoundType sndType = SoundType.None;
void GetSound() {
Vector3 pos = p.nextPos;
Vector3 pos = p.interp.nextPos;
AABB bounds = p.Bounds;
sndType = SoundType.None;
anyNonAir = false;

View File

@ -26,12 +26,13 @@ namespace ClassicalSharp.Entities {
get { return (float)PhysicsComponent.GetMaxHeight(physics.jumpVel); }
}
internal float curWalkTime, curSwing;
internal float curSwing;
internal CollisionsComponent collisions;
public HacksComponent Hacks;
internal PhysicsComponent physics;
internal InputComponent input;
internal SoundComponent sound;
internal LocalInterpComponent interp;
public LocalPlayer(Game game) : base(game) {
DisplayName = game.Username;
@ -43,6 +44,7 @@ namespace ClassicalSharp.Entities {
physics = new PhysicsComponent(game, this);
input = new InputComponent(game, this);
sound = new SoundComponent(game, this);
interp = new LocalInterpComponent(game, this);
physics.hacks = Hacks; input.Hacks = Hacks;
physics.collisions = collisions;
@ -55,9 +57,7 @@ namespace ClassicalSharp.Entities {
&& Hacks.CanSpeed ? 1 : 0.5f;
OldVelocity = Velocity;
float xMoving = 0, zMoving = 0;
lastPos = Position = nextPos;
lastYaw = nextYaw;
lastPitch = nextPitch;
interp.AdvanceState();
bool wasOnGround = onGround;
HandleInput(ref xMoving, ref zMoving);
@ -65,20 +65,17 @@ namespace ClassicalSharp.Entities {
physics.UpdateVelocityState(xMoving, zMoving);
physics.PhysicsTick(xMoving, zMoving);
nextPos = Position;
Position = lastPos;
anim.UpdateAnimState(lastPos, nextPos, delta);
interp.nextPos = Position; Position = interp.lastPos;
anim.UpdateAnimState(interp.lastPos, interp.nextPos, delta);
CheckSkin();
sound.Tick(wasOnGround);
UpdateCurrentBodyYaw();
}
public override void RenderModel(double deltaTime, float t) {
anim.GetCurrentAnimState(t);
curSwing = Utils.Lerp(anim.swingO, anim.swingN, t);
curWalkTime = Utils.Lerp(anim.walkTimeO, anim.walkTimeN, t);
if (!game.Camera.IsThirdPerson) return;
Model.Render(this);
}
@ -118,65 +115,18 @@ namespace ClassicalSharp.Entities {
}
}
internal Vector3 lastPos, nextPos;
internal float lastYaw, nextYaw, lastPitch, nextPitch;
float newYaw, oldYaw;
int yawStateCount;
float[] yawStates = new float[15];
public override void SetLocation(LocationUpdate update, bool interpolate) {
if (update.IncludesPosition) {
nextPos = update.RelativePosition ? nextPos + update.Pos : update.Pos;
double blockOffset = nextPos.Y - Math.Floor(nextPos.Y);
if (blockOffset < Entity.Adjustment)
nextPos.Y += Entity.Adjustment;
if (!interpolate) {
lastPos = Position = nextPos;
}
}
if (update.IncludesOrientation) {
nextYaw = update.Yaw;
nextPitch = update.Pitch;
if (!interpolate) {
lastYaw = YawDegrees = nextYaw;
lastPitch = PitchDegrees = nextPitch;
HeadYawDegrees = YawDegrees;
yawStateCount = 0;
} else {
for (int i = 0; i < 3; i++)
AddYaw(Utils.LerpAngle(lastYaw, nextYaw, (i + 1) / 3f));
}
}
interp.SetLocation(update, interpolate);
}
/// <summary> Linearly interpolates position and rotation between the previous and next state. </summary>
public void SetInterpPosition(float t) {
if (!Hacks.WOMStyleHacks || !Hacks.Noclip)
Position = Vector3.Lerp(lastPos, nextPos, t);
Position = Vector3.Lerp(interp.lastPos, interp.nextPos, t);
HeadYawDegrees = Utils.LerpAngle(lastYaw, nextYaw, t);
YawDegrees = Utils.LerpAngle(oldYaw, newYaw, t);
PitchDegrees = Utils.LerpAngle(lastPitch, nextPitch, t);
}
void AddYaw(float state) {
if (yawStateCount == yawStates.Length)
RemoveOldest(yawStates, ref yawStateCount);
yawStates[yawStateCount++] = state;
}
void UpdateCurrentBodyYaw() {
oldYaw = newYaw;
if (yawStateCount > 0) {
newYaw = yawStates[0];
RemoveOldest(yawStates, ref yawStateCount);
}
}
void RemoveOldest<T>(T[] array, ref int count) {
for (int i = 0; i < array.Length - 1; i++)
array[i] = array[i + 1];
count--;
HeadYawDegrees = Utils.LerpAngle(interp.lastHeadYaw, interp.nextHeadYaw, t);
YawDegrees = Utils.LerpAngle(interp.lastYaw, interp.nextYaw, t);
PitchDegrees = Utils.LerpAngle(interp.lastPitch, interp.nextPitch, t);
}
public void Init(Game game) {

View File

@ -2,7 +2,7 @@
using System;
using OpenTK;
namespace ClassicalSharp.Entities {
namespace ClassicalSharp.Entities.Mobs {
public abstract class AI {

View File

@ -2,7 +2,7 @@
using System;
using OpenTK;
namespace ClassicalSharp.Entities {
namespace ClassicalSharp.Entities.Mobs {
public sealed class FleeAI : AI {

View File

@ -2,7 +2,7 @@
using System;
using OpenTK;
namespace ClassicalSharp.Entities {
namespace ClassicalSharp.Entities.Mobs {
public sealed class HostileAI : AI {

View File

@ -0,0 +1,42 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using OpenTK;
namespace ClassicalSharp.Entities.Mobs {
public class MobEntity : Entity {
LocalInterpComponent interp;
public MobEntity(Game game, string model) : base(game) {
StepSize = 0.5f;
SetModel(model);
interp = new LocalInterpComponent(game, this);
}
public override void Despawn() { }
public override void RenderName() { }
// TODO: this is just so the entities do something, remove later
static Random rand = new Random();
public override void Tick(double delta) {
interp.AdvanceState();
float inc = rand.Next(0, 10);
LocationUpdate update = LocationUpdate.MakeOri(interp.nextHeadYaw + inc, 0);
SetLocation(update, true);
}
public override void SetLocation(LocationUpdate update, bool interpolate) {
interp.SetLocation(update, interpolate);
}
public override void RenderModel(double deltaTime, float t) {
Position = Vector3.Lerp(interp.lastPos, interp.nextPos, t);
HeadYawDegrees = Utils.LerpAngle(interp.lastHeadYaw, interp.nextHeadYaw, t);
YawDegrees = Utils.LerpAngle(interp.lastYaw, interp.nextYaw, t);
PitchDegrees = Utils.LerpAngle(interp.lastPitch, interp.nextPitch, t);
anim.GetCurrentAnimState(t);
Model.Render(this);
}
}
}

View File

@ -6,12 +6,12 @@ namespace ClassicalSharp.Entities {
public sealed class NetPlayer : Player {
InterpolatedComponent interp;
NetInterpComponent interp;
public NetPlayer(string displayName, string skinName, Game game, byte id) : base(game) {
DisplayName = displayName;
SkinName = skinName;
SkinIdentifier = "skin_" + id;
interp = new InterpolatedComponent(game, this);
interp = new NetInterpComponent(game, this);
}
public override void SetLocation(LocationUpdate update, bool interpolate) {

View File

@ -84,7 +84,7 @@ namespace ClassicalSharp {
// NOTE: We need to also test against nextPos here, because otherwise
// we can fall through the block as collision is performed against nextPos
AABB localBB = AABB.Make(p.Position, p.Size);
localBB.Min.Y = Math.Min(p.nextPos.Y, localBB.Min.Y);
localBB.Min.Y = Math.Min(p.interp.nextPos.Y, localBB.Min.Y);
if (p.Hacks.Noclip || !localBB.Intersects(blockBB)) return true;
if (p.Hacks.CanPushbackBlocks && p.Hacks.PushbackPlacing && p.Hacks.Enabled)
@ -94,7 +94,7 @@ namespace ClassicalSharp {
if (localBB.Intersects(blockBB)) return false;
// Push player up if they are jumping and trying to place a block underneath them.
Vector3 next = game.LocalPlayer.nextPos;
Vector3 next = game.LocalPlayer.interp.nextPos;
next.Y = pos.Y + game.BlockInfo.MaxBB[block].Y + Entity.Adjustment;
LocationUpdate update = LocationUpdate.MakePos(next, false);
game.LocalPlayer.SetLocation(update, false);

View File

@ -1,5 +1,8 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using ClassicalSharp.Entities;
using ClassicalSharp.Entities.Mobs;
using OpenTK;
using OpenTK.Input;
namespace ClassicalSharp.Mode {
@ -40,7 +43,8 @@ namespace ClassicalSharp.Mode {
}
public bool PickEntity(byte id) {
return false;
game.Chat.Add("PICKED ON: " + id + "," + game.Entities[id].ModelName);
return true;
}
@ -92,6 +96,17 @@ namespace ClassicalSharp.Mode {
public void OnNewMapLoaded(Game game) {
game.Chat.Add("&fScore: &e" + score, MessageType.Status1);
string[] models = { "sheep", "pig", "skeleton", "zombie", "creeper" };
for (int i = 0; i < 254; i++) {
MobEntity fail = new MobEntity(game, models[rnd.Next(models.Length)]);
float x = rnd.Next(0, game.World.Width) + 0.5f;
float z = rnd.Next(0, game.World.Length) + 0.5f;
Vector3 pos = Respawn.FindSpawnPosition(game, x, z, fail.Size);
fail.SetLocation(LocationUpdate.MakePos(pos, false), false);
game.Entities[i] = fail;
}
}
public void Init(Game game) {

View File

@ -110,24 +110,12 @@ namespace ClassicalSharp.Singleplayer {
this.generator = generator;
game.Gui.SetNewScreen(new LoadingMapScreen(game, "Generating level", "Generating.."));
generator.GenerateAsync(game, width, height, length, seed);
}
}
void ResetPlayerPosition() {
Vector3 spawn = default(Vector3);
spawn.X = (game.World.Width / 2) + 0.5f;
spawn.Y = game.World.Height + Entity.Adjustment;
spawn.Z = (game.World.Length / 2) + 0.5f;
AABB bb = AABB.Make(spawn, game.LocalPlayer.Size);
spawn.Y = 0;
for (int y = game.World.Height; y >= 0; y--) {
float highestY = Respawn.HighestFreeY(game, ref bb);
if (highestY != float.NegativeInfinity) {
spawn.Y = highestY; break;
}
bb.Min.Y -= 1; bb.Max.Y -= 1;
}
float x = (game.World.Width / 2) + 0.5f;
float z = (game.World.Length / 2) + 0.5f;
Vector3 spawn = Respawn.FindSpawnPosition(game, x, z, game.LocalPlayer.Size);
LocationUpdate update = LocationUpdate.MakePosAndOri(spawn, 0, 0, false);
game.LocalPlayer.SetLocation(update, false);

View File

@ -94,14 +94,14 @@ namespace ClassicalSharp {
static readonly float sensiFactor = 0.0002f / 3 * Utils.Rad2Deg;
private void UpdateMouseRotation() {
float sensitivity = sensiFactor * game.MouseSensitivity;
float yaw = player.nextYaw + delta.X * sensitivity;
float yaw = player.interp.nextHeadYaw + delta.X * sensitivity;
float yAdj = game.InvertMouse ? -delta.Y * sensitivity : delta.Y * sensitivity;
float pitch = player.nextPitch + yAdj;
float pitch = player.interp.nextPitch + yAdj;
LocationUpdate update = LocationUpdate.MakeOri(yaw, pitch);
// Need to make sure we don't cross the vertical axes, because that gets weird.
if (update.Pitch >= 90 && update.Pitch <= 270)
update.Pitch = player.nextPitch < 180 ? 89.9f : 270.1f;
update.Pitch = player.interp.nextPitch < 180 ? 89.9f : 270.1f;
game.LocalPlayer.SetLocation(update, true);
}

View File

@ -1,5 +1,6 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using ClassicalSharp.Entities;
using ClassicalSharp.Physics;
using OpenTK;
@ -31,5 +32,21 @@ namespace ClassicalSharp {
}
return spawnY;
}
public static Vector3 FindSpawnPosition(Game game, float x, float z, Vector3 modelSize) {
Vector3 spawn = new Vector3(x, 0, z);
spawn.Y = game.World.Height + Entity.Adjustment;
AABB bb = AABB.Make(spawn, modelSize);
spawn.Y = 0;
for (int y = game.World.Height; y >= 0; y--) {
float highestY = HighestFreeY(game, ref bb);
if (highestY != float.NegativeInfinity) {
spawn.Y = highestY; break;
}
bb.Min.Y -= 1; bb.Max.Y -= 1;
}
return spawn;
}
}
}