more concise interpolation, fix last commit

This commit is contained in:
UnknownShadow200 2017-01-25 22:30:56 +11:00
parent 55093847db
commit e7aa519846
21 changed files with 243 additions and 227 deletions

View File

@ -73,7 +73,7 @@ namespace ClassicalSharp.Gui.Screens {
game.Server.RetrieveTexturePack(game.World.TextureUrl);
LocalPlayer p = game.LocalPlayer;
LocationUpdate update = LocationUpdate.MakePosAndOri(p.Spawn, p.SpawnYaw, p.SpawnPitch, false);
LocationUpdate update = LocationUpdate.MakePosAndOri(p.Spawn, p.SpawnRotY, p.SpawnHeadX, false);
p.SetLocation(update, false);
}
} catch (Exception ex) {

View File

@ -52,10 +52,10 @@ namespace ClassicalSharp {
static byte RotateOther(Game game, byte block, string name, Vector3 offset) {
// Fence type blocks
if (game.BlockInfo.FindID(name + "-UD") == -1) {
float yaw = game.LocalPlayer.HeadY;
if (yaw < 0) yaw += 360;
float headY = game.LocalPlayer.HeadY;
if (headY < 0) headY += 360;
if (yaw < 45 || (yaw >= 135 && yaw < 225) || yaw > 315)
if (headY < 45 || (headY >= 135 && headY < 225) || headY > 315)
return Find(game, block, name + "-WE");
return Find(game, block, name + "-NS");
}

View File

@ -150,6 +150,7 @@
<Compile Include="Blocks\BlockInfo.Atlas.cs" />
<Compile Include="Blocks\DefaultSet.cs" />
<Compile Include="Commands\SinglePlayerCommands.cs" />
<Compile Include="Entities\Components\IInterpComponent.cs" />
<Compile Include="Entities\Components\LocalInterpComponent.cs" />
<Compile Include="Entities\Mobs\AI\AI.cs" />
<Compile Include="Entities\Mobs\AI\FleeAI.cs" />

View File

@ -0,0 +1,182 @@
// 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 orientation over time. </summary>
public abstract class IInterpComponent {
public abstract void SetLocation(LocationUpdate update, bool interpolate);
public virtual void AdvanceState() {
prevRotY = nextRotY;
if (rotYStateCount == 0) return;
nextRotY = rotYStates[0];
RemoveOldest(rotYStates, ref rotYStateCount);
}
public State prev, next;
public float prevRotY, nextRotY;
public struct State {
public Vector3 Pos;
public float HeadX, HeadY, RotX, RotZ;
public State(Vector3 pos, float headX, float headY, float rotX, float rotZ) {
this.Pos = pos;
this.HeadX = headX; this.HeadY = headY;
this.RotX = rotX; this.RotZ = rotZ;
}
}
public void LerpAngles(float t) {
entity.HeadX = Utils.LerpAngle(prev.HeadX, next.HeadX, t);
entity.HeadY = Utils.LerpAngle(prev.HeadY, next.HeadY, t);
entity.RotX = Utils.LerpAngle(prev.RotX, next.RotX, t);
entity.RotY = Utils.LerpAngle(prevRotY, nextRotY, t);
entity.RotZ = Utils.LerpAngle(prev.RotZ, next.RotZ, t);
}
protected Entity entity;
protected int rotYStateCount;
protected float[] rotYStates = new float[15];
protected void AddRotY(float state) {
if (rotYStateCount == rotYStates.Length)
RemoveOldest(rotYStates, ref rotYStateCount);
rotYStates[rotYStateCount++] = state;
}
protected void RemoveOldest<T>(T[] array, ref int count) {
for (int i = 0; i < array.Length - 1; i++)
array[i] = array[i + 1];
count--;
}
}
public sealed class NetInterpComponent : IInterpComponent {
public NetInterpComponent(Game game, Entity entity) {
this.entity = entity;
}
// Last known position and orientation sent by the server.
internal Vector3 curPos;
internal float curRotX, curRotZ, curHeadX, curHeadY;
public override void SetLocation(LocationUpdate update, bool interpolate) {
Vector3 lastPos = curPos;
float lastRotX = curRotX, lastRotZ = curRotZ;
float lastHeadX = curHeadX, lastHeadY = curHeadY;
if (update.IncludesPosition) {
curPos = update.RelativePosition ? curPos + update.Pos : update.Pos;
}
curRotX = Next(update.RotX, curRotX);
curRotZ = Next(update.RotZ, curRotZ);
curHeadX = Next(update.HeadX, curHeadX);
curHeadY = Next(update.RotY, curHeadY);
if (!interpolate) {
stateCount = 0;
next = prev = new State(curPos, curHeadX, curHeadY, curRotX, curRotZ);
rotYStateCount = 0;
nextRotY = prevRotY = curHeadY;
} else {
// Smoother interpolation by also adding midpoint.
Vector3 midPos = Vector3.Lerp(lastPos, curPos, 0.5f);
float midRotX = Utils.LerpAngle(lastRotX, curRotX, 0.5f);
float midRotZ = Utils.LerpAngle(lastRotZ, curRotZ, 0.5f);
float midHeadX = Utils.LerpAngle(lastHeadX, curHeadX, 0.5f);
float midHeadY = Utils.LerpAngle(lastHeadY, curHeadY, 0.5f);
AddState(new State(midPos, midHeadX, midHeadY, midRotX, midRotZ));
AddState(new State(curPos, curHeadX, curHeadY, curRotX, curRotZ));
for (int i = 0; i < 3; i++)
AddRotY(Utils.LerpAngle(lastHeadY, curHeadY, (i + 1) / 3f));
}
}
public override void AdvanceState() {
prev = next; prevRotY = nextRotY;
if (stateCount > 0) {
next = states[0];
RemoveOldest(states, ref stateCount);
}
base.AdvanceState();
}
State[] states = new State[10];
int stateCount;
static float Next(float next, float cur) {
if (float.IsNaN(next)) return cur;
return next;
}
void AddState(State state) {
if (stateCount == states.Length)
RemoveOldest(states, ref stateCount);
states[stateCount++] = state;
}
}
/// <summary> Entity component that performs interpolation of position and orientation over time. </summary>
public sealed class LocalInterpComponent : IInterpComponent {
public LocalInterpComponent(Game game, Entity entity) {
this.entity = entity;
}
public override void SetLocation(LocationUpdate update, bool interpolate) {
if (update.IncludesPosition) {
next.Pos = update.RelativePosition ? next.Pos + update.Pos : update.Pos;
double blockOffset = next.Pos.Y - Math.Floor(next.Pos.Y);
if (blockOffset < Entity.Adjustment)
next.Pos.Y += Entity.Adjustment;
if (!interpolate) {
prev.Pos = entity.Position = next.Pos;
}
}
next.RotX = Next(update.RotX, next.RotX, ref prev.RotX, interpolate);
next.RotZ = Next(update.RotZ, next.RotZ, ref prev.RotZ, interpolate);
next.HeadX = Next(update.HeadX, next.HeadX, ref prev.HeadX, interpolate);
next.HeadY = Next(update.RotY, next.HeadY, ref prev.HeadY, interpolate);
if (!float.IsNaN(update.RotY)) {
// Body Y rotation lags slightly behind
if (!interpolate) {
nextRotY = update.RotY; entity.RotY = update.RotY;
rotYStateCount = 0;
} else {
for (int i = 0; i < 3; i++)
AddRotY(Utils.LerpAngle(prev.HeadY, next.HeadY, (i + 1) / 3f));
nextRotY = rotYStates[0];
}
}
LerpAngles(0);
}
public override void AdvanceState() {
prev = next; entity.Position = next.Pos;
base.AdvanceState();
}
static float Next(float next, float cur, ref float last, bool interpolate) {
if (float.IsNaN(next)) return cur;
if (!interpolate) last = next;
return next;
}
}
}

View File

@ -29,8 +29,8 @@ namespace ClassicalSharp.Entities {
p.Spawn = entity.Position;
p.Spawn.X = Utils.Floor(p.Spawn.X) + 0.5f;
p.Spawn.Z = Utils.Floor(p.Spawn.Z) + 0.5f;
p.SpawnYaw = entity.RotY;
p.SpawnPitch = entity.HeadX;
p.SpawnRotY = entity.RotY;
p.SpawnHeadX = entity.HeadX;
DoRespawn();
} else if (key == keys[KeyBind.Fly] && Hacks.CanFly && Hacks.Enabled) {
Hacks.Flying = !Hacks.Flying;
@ -58,7 +58,7 @@ namespace ClassicalSharp.Entities {
FindHighestFree(ref spawn);
spawn.Y += 2/16f;
LocationUpdate update = LocationUpdate.MakePosAndOri(spawn, p.SpawnYaw, p.SpawnPitch, false);
LocationUpdate update = LocationUpdate.MakePosAndOri(spawn, p.SpawnRotY, p.SpawnHeadX, false);
entity.SetLocation(update, false);
entity.Velocity = Vector3.Zero;

View File

@ -5,84 +5,5 @@ 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 lastHeadY, lastHeadX, lastRotX, lastRotY, lastRotZ;
internal float nextHeadY, nextHeadX, nextRotX, nextRotY, nextRotZ;
int rotYStateCount;
float[] rotYStates = 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;
}
}
nextRotX = Next(update.RotX, nextRotX, ref lastRotX, interpolate);
nextRotZ = Next(update.RotZ, nextRotZ, ref lastRotZ, interpolate);
nextHeadX = Next(update.HeadX, nextHeadX, ref lastHeadX, interpolate);
if (float.IsNaN(update.RotY)) return;
nextHeadY = update.RotY;
if (!interpolate) {
lastHeadY = update.RotY; entity.HeadY = update.RotY; entity.RotY = update.RotY;
rotYStateCount = 0;
} else {
for (int i = 0; i < 3; i++)
AddRotY(Utils.LerpAngle(lastHeadY, nextHeadY, (i + 1) / 3f));
}
}
public void AdvanceState() {
lastPos = entity.Position = nextPos;
lastHeadY = nextHeadY; lastHeadX = nextHeadX;
lastRotX = nextRotX; lastRotY = nextRotY; lastRotZ = nextRotZ;
if (rotYStateCount > 0) {
nextRotY = rotYStates[0];
RemoveOldest(rotYStates, ref rotYStateCount);
}
}
public void LerpAngles(float t) {
entity.HeadX = Utils.LerpAngle(lastHeadX, nextHeadX, t);
entity.HeadY = Utils.LerpAngle(lastHeadY, nextHeadY, t);
entity.RotX = Utils.LerpAngle(lastRotX, nextRotX, t);
entity.RotY = Utils.LerpAngle(lastRotY, nextRotY, t);
entity.RotZ = Utils.LerpAngle(lastRotZ, nextRotZ, t);
}
static float Next(float next, float cur, ref float last, bool interpolate) {
if (float.IsNaN(next)) return cur;
if (!interpolate) last = next;
return next;
}
void AddRotY(float state) {
if (rotYStateCount == rotYStates.Length)
RemoveOldest(rotYStates, ref rotYStateCount);
rotYStates[rotYStateCount++] = 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

@ -5,94 +5,6 @@ using OpenTK;
namespace ClassicalSharp.Entities {
/// <summary> Entity component that performs interpolation of position and model head yaw over time. </summary>
public sealed class NetInterpComponent {
Entity entity;
public NetInterpComponent(Game game, Entity entity) {
this.entity = entity;
}
// Last known position and orientation sent by the server.
internal Vector3 serverPos;
internal float serverRotY, serverHeadX;
public void SetLocation(LocationUpdate update, bool interpolate) {
/*Vector3 lastPos = serverPos;
float lastRotY = serverRotY, lastHeadX = serverHeadX;
if (update.IncludesPosition) {
serverPos = update.RelativePosition ? serverPos + update.Pos : update.Pos;
}
if (update.IncludesOrientation) {
serverRotY = update.RotY; serverHeadX = update.HeadX;
}
if (!interpolate) {
stateCount = 0;
newState = oldState = new State(entity.tickCount, serverPos, serverRotY, serverHeadX);
rotYStateCount = 0;
newYaw = oldYaw = serverRotY;
} else {
// Smoother interpolation by also adding midpoint.
Vector3 midPos = Vector3.Lerp(lastPos, serverPos, 0.5f);
float midYaw = Utils.LerpAngle(lastRotY, serverRotY, 0.5f);
float midPitch = Utils.LerpAngle(lastHeadX, serverHeadX, 0.5f);
AddState(new State(entity.tickCount, midPos, midYaw, midPitch));
AddState(new State(entity.tickCount, serverPos, serverRotY, serverHeadX));
for (int i = 0; i < 3; i++)
AddYaw(Utils.LerpAngle(lastRotY, serverRotY, (i + 1) / 3f));
}*/
}
public struct State {
public int tick;
public Vector3 pos;
public float headYaw, pitch;
public State(int tick, Vector3 pos, float headYaw, float pitch) {
this.tick = tick;
this.pos = pos;
this.headYaw = headYaw;
this.pitch = pitch;
}
}
State[] states = new State[10];
float[] yawStates = new float[15];
public State newState, oldState;
public float newYaw, oldYaw;
int stateCount, rotYStateCount;
void AddState(State state) {
if (stateCount == states.Length)
RemoveOldest(states, ref stateCount);
states[stateCount++] = state;
}
void AddYaw(float state) {
if (rotYStateCount == yawStates.Length)
RemoveOldest(yawStates, ref rotYStateCount);
yawStates[rotYStateCount++] = state;
}
public void UpdateCurrentState() {
oldState = newState;
oldYaw = newYaw;
if (stateCount > 0) {
//if (states[0].tick > tickCount - 2) return; // 100 ms delay
newState = states[0];
RemoveOldest(states, ref stateCount);
}
if (rotYStateCount > 0) {
newYaw = yawStates[0];
RemoveOldest(yawStates, ref rotYStateCount);
}
}
void RemoveOldest<T>(T[] array, ref int count) {
for (int i = 0; i < array.Length - 1; i++)
array[i] = array[i + 1];
count--;
}
}
/// <summary> Entity component that performs interpolation of position and orientation over time. </summary>
}

View File

@ -22,7 +22,7 @@ namespace ClassicalSharp.Entities {
Vector3 lastSoundPos;
public void Tick(bool wasOnGround) {
Vector3 soundPos = p.interp.nextPos;
Vector3 soundPos = p.interp.next.Pos;
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.interp.nextPos;
Vector3 pos = p.interp.next.Pos;
AABB bounds = p.Bounds;
sndType = SoundType.None;
anyNonAir = false;

View File

@ -12,7 +12,7 @@ namespace ClassicalSharp.Entities {
/// <summary> Position the player's position is set to when the 'respawn' key binding is pressed. </summary>
public Vector3 Spawn;
public float SpawnYaw, SpawnPitch;
public float SpawnRotY, SpawnHeadX;
/// <summary> The distance (in blocks) that players are allowed to
/// reach to and interact/modify blocks in. </summary>
@ -63,8 +63,8 @@ namespace ClassicalSharp.Entities {
physics.UpdateVelocityState(xMoving, zMoving);
physics.PhysicsTick(xMoving, zMoving);
interp.nextPos = Position; Position = interp.lastPos;
anim.UpdateAnimState(interp.lastPos, interp.nextPos, delta);
interp.next.Pos = Position; Position = interp.prev.Pos;
anim.UpdateAnimState(interp.prev.Pos, interp.next.Pos, delta);
CheckSkin();
sound.Tick(wasOnGround);
@ -120,7 +120,7 @@ namespace ClassicalSharp.Entities {
/// <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(interp.lastPos, interp.nextPos, t);
Position = Vector3.Lerp(interp.prev.Pos, interp.next.Pos, t);
interp.LerpAngles(t);
}

View File

@ -34,8 +34,8 @@ namespace ClassicalSharp.Entities.Mobs {
bool wasOnGround = onGround;
physics.UpdateVelocityState(xMoving, zMoving);
physics.PhysicsTick(xMoving, zMoving);
interp.nextPos = Position; Position = interp.lastPos;
anim.UpdateAnimState(interp.lastPos, interp.nextPos, delta);
interp.next.Pos = Position; Position = interp.prev.Pos;
anim.UpdateAnimState(interp.prev.Pos, interp.next.Pos, delta);
}
public override void SetLocation(LocationUpdate update, bool interpolate) {
@ -43,7 +43,7 @@ namespace ClassicalSharp.Entities.Mobs {
}
public override void RenderModel(double deltaTime, float t) {
Position = Vector3.Lerp(interp.lastPos, interp.nextPos, t);
Position = Vector3.Lerp(interp.prev.Pos, interp.next.Pos, t);
interp.LerpAngles(t);
anim.GetCurrentAnimState(t);
Model.Render(this);

View File

@ -86,11 +86,11 @@ namespace ClassicalSharp.Model {
col = game.World.IsValidPos(P) ? game.Lighting.LightCol(P.X, P.Y, P.Z) : game.Lighting.Outside;
// Adjust pitch so angle when looking straight down is 0.
float adjPitch = realP.HeadX - 90;
if (adjPitch < 0) adjPitch += 360;
float adjHeadX = realP.HeadX - 90;
if (adjHeadX < 0) adjHeadX += 360;
// Adjust colour so held block is brighter when looking straght up
float t = Math.Abs(adjPitch - 180) / 180;
float t = Math.Abs(adjHeadX - 180) / 180;
float colScale = Utils.Lerp(0.9f, 0.7f, t);
col = FastColour.ScalePacked(col, colScale);
block = ((FakePlayer)p).Block;

View File

@ -21,16 +21,16 @@ namespace ClassicalSharp.Entities {
public override void Tick(double delta) {
CheckSkin();
tickCount++;
interp.UpdateCurrentState();
anim.UpdateAnimState(interp.oldState.pos, interp.newState.pos, delta);
interp.AdvanceState();
anim.UpdateAnimState(interp.prev.Pos, interp.next.Pos, delta);
}
bool shouldRender = false;
public override void RenderModel(double deltaTime, float t) {
Position = Vector3.Lerp(interp.oldState.pos, interp.newState.pos, t);
HeadY = Utils.LerpAngle(interp.oldState.headYaw, interp.newState.headYaw, t);
RotY = Utils.LerpAngle(interp.oldYaw, interp.newYaw, t);
HeadX = Utils.LerpAngle(interp.oldState.pitch, interp.newState.pitch, t);
Position = Vector3.Lerp(interp.prev.Pos, interp.next.Pos, t);
HeadY = Utils.LerpAngle(interp.prev.HeadY, interp.next.HeadY, t);
RotY = Utils.LerpAngle(interp.prevRotY, interp.nextRotY, t);
HeadX = Utils.LerpAngle(interp.prev.HeadX, interp.next.HeadX, t);
anim.GetCurrentAnimState(t);
shouldRender = Model.ShouldRender(this, game.Culling);

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.interp.nextPos.Y, localBB.Min.Y);
localBB.Min.Y = Math.Min(p.interp.next.Pos.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.interp.nextPos;
Vector3 next = game.LocalPlayer.interp.next.Pos;
next.Y = pos.Y + game.BlockInfo.MaxBB[block].Y + Entity.Adjustment;
LocationUpdate update = LocationUpdate.MakePos(next, false);
game.LocalPlayer.SetLocation(update, false);

View File

@ -67,11 +67,11 @@ namespace ClassicalSharp.Map {
nbt.Write(NbtTagType.Int8);
nbt.Write("H");
nbt.WriteUInt8((byte)Utils.DegreesToPacked(p.SpawnYaw));
nbt.WriteUInt8((byte)Utils.DegreesToPacked(p.SpawnRotY));
nbt.Write(NbtTagType.Int8);
nbt.Write("P");
nbt.WriteUInt8((byte)Utils.DegreesToPacked(p.SpawnPitch));
nbt.WriteUInt8((byte)Utils.DegreesToPacked(p.SpawnHeadX));
nbt.Write(NbtTagType.End);
}

View File

@ -40,9 +40,9 @@ namespace ClassicalSharp.Map {
p.Spawn.Y = (short)spawn["Y"].Value;
p.Spawn.Z = (short)spawn["Z"].Value;
if (spawn.ContainsKey("H"))
p.SpawnYaw = (float)Utils.PackedToDegrees((byte)spawn["H"].Value);
p.SpawnRotY = (float)Utils.PackedToDegrees((byte)spawn["H"].Value);
if (spawn.ContainsKey("P"))
p.SpawnPitch = (float)Utils.PackedToDegrees((byte)spawn["P"].Value);
p.SpawnHeadX = (float)Utils.PackedToDegrees((byte)spawn["P"].Value);
map.Uuid = new Guid((byte[])children["UUID"].Value);
width = (short)children["X"].Value;

View File

@ -27,8 +27,8 @@ namespace ClassicalSharp.Map {
p.Spawn.X = r.ReadInt32() / 32f;
p.Spawn.Y = r.ReadInt32() / 32f;
p.Spawn.Z = r.ReadInt32() / 32f;
p.SpawnYaw = (float)Utils.PackedToDegrees(r.ReadByte());
p.SpawnPitch = (float)Utils.PackedToDegrees(r.ReadByte());
p.SpawnRotY = (float)Utils.PackedToDegrees(r.ReadByte());
p.SpawnHeadX = (float)Utils.PackedToDegrees(r.ReadByte());
r.ReadUInt32(); // date modified
r.ReadUInt32(); // date created

View File

@ -31,8 +31,8 @@ namespace ClassicalSharp.Map {
p.Spawn.X = r.ReadUInt16();
p.Spawn.Z = r.ReadUInt16();
p.Spawn.Y = r.ReadUInt16();
p.SpawnYaw = (float)Utils.PackedToDegrees(r.ReadByte());
p.SpawnPitch = (float)Utils.PackedToDegrees(r.ReadByte());
p.SpawnRotY = (float)Utils.PackedToDegrees(r.ReadByte());
p.SpawnHeadX = (float)Utils.PackedToDegrees(r.ReadByte());
if (header == Version)
r.ReadUInt16(); // pervisit and perbuild perms

View File

@ -25,7 +25,7 @@ namespace ClassicalSharp {
public abstract void SendChat(string text, bool partial);
/// <summary> Informs the server of the client's current position and orientation. </summary>
public abstract void SendPosition(Vector3 pos, float yaw, float pitch);
public abstract void SendPosition(Vector3 pos, float rotY, float headX);
/// <summary> Informs the server that using the given mouse button,
/// the client clicked on a particular block or entity. </summary>

View File

@ -13,8 +13,8 @@ namespace ClassicalSharp.Network {
classic.SendChat(text, partial);
}
public override void SendPosition(Vector3 pos, float yaw, float pitch) {
classic.SendPosition(pos, yaw, pitch);
public override void SendPosition(Vector3 pos, float rotY, float headX) {
classic.SendPosition(pos, rotY, headX);
}
public override void SendPlayerClick(MouseButton button, bool buttonDown, byte targetId, PickedPos pos) {
@ -58,8 +58,8 @@ namespace ClassicalSharp.Network {
if (id != 0xFF) return;
LocalPlayer p = game.LocalPlayer;
p.Spawn = p.Position;
p.SpawnYaw = p.HeadY;
p.SpawnPitch = p.HeadX;
p.SpawnRotY = p.HeadY;
p.SpawnHeadX = p.HeadX;
}
internal void RemoveEntity(byte id) {

View File

@ -127,8 +127,8 @@ namespace ClassicalSharp.Renderers {
void ViewDistanceChanged(object sender, EventArgs e) {
lastCamPos = Utils.MaxPos();
lastYaw = float.MaxValue;
lastPitch = float.MaxValue;
lastRotY = float.MaxValue;
lastHeadX = float.MaxValue;
}
internal void ResetUsedFlags() {
@ -168,8 +168,8 @@ namespace ClassicalSharp.Renderers {
CreateChunkCache();
builder.OnNewMapLoaded();
lastCamPos = Utils.MaxPos();
lastYaw = float.MaxValue;
lastPitch = float.MaxValue;
lastRotY = float.MaxValue;
lastHeadX = float.MaxValue;
}
void CreateChunkCache() {
@ -316,18 +316,18 @@ namespace ClassicalSharp.Renderers {
LocalPlayer p = game.LocalPlayer;
Vector3 cameraPos = game.CurrentCameraPos;
bool samePos = cameraPos == lastCamPos && p.HeadY == lastYaw
&& p.HeadX == lastPitch;
bool samePos = cameraPos == lastCamPos && p.HeadY == lastRotY
&& p.HeadX == lastHeadX;
renderer.renderCount = samePos ? UpdateChunksStill(ref chunkUpdates) :
UpdateChunksAndVisibility(ref chunkUpdates);
lastCamPos = cameraPos;
lastYaw = p.HeadY; lastPitch = p.HeadX;
lastRotY = p.HeadY; lastHeadX = p.HeadX;
if (!samePos || chunkUpdates != 0)
ResetUsedFlags();
}
Vector3 lastCamPos;
float lastYaw, lastPitch;
float lastRotY, lastHeadX;
int UpdateChunksAndVisibility(ref int chunkUpdates) {
ChunkInfo[] chunks = renderer.chunks, render = renderer.renderChunks;

View File

@ -35,7 +35,7 @@ namespace ClassicalSharp {
/// <summary> Calculates the picked block based on the camera's current position. </summary>
public virtual void GetPickedBlock(PickedPos pos) { }
protected float AdjustPitch(float value) {
protected float AdjustHeadX(float value) {
if (value >= 90.0f && value <= 90.1f) return 90.1f * Utils.Deg2Rad;
if (value >= 89.9f && value <= 90.0f) return 89.9f * Utils.Deg2Rad;
if (value >= 270.0f && value <= 270.1f) return 270.1f * Utils.Deg2Rad;
@ -62,7 +62,7 @@ namespace ClassicalSharp {
public override void GetPickedBlock(PickedPos pos) {
Vector3 dir = Utils.GetDirVector(player.HeadYRadians,
AdjustPitch(player.HeadX));
AdjustHeadX(player.HeadX));
Vector3 eyePos = player.EyePosition;
float reach = game.LocalPlayer.ReachDistance;
Picking.CalculatePickedBlock(game, eyePos, dir, reach, pos);
@ -94,14 +94,14 @@ namespace ClassicalSharp {
static readonly float sensiFactor = 0.0002f / 3 * Utils.Rad2Deg;
private void UpdateMouseRotation() {
float sensitivity = sensiFactor * game.MouseSensitivity;
float rotY = player.interp.nextHeadY + delta.X * sensitivity;
float rotY = player.interp.next.HeadY + delta.X * sensitivity;
float yAdj = game.InvertMouse ? -delta.Y * sensitivity : delta.Y * sensitivity;
float headX = player.interp.nextHeadX + yAdj;
float headX = player.interp.next.HeadX + yAdj;
LocationUpdate update = LocationUpdate.MakeOri(rotY, headX);
// Need to make sure we don't cross the vertical axes, because that gets weird.
if (update.HeadX >= 90 && update.HeadX <= 270)
update.HeadX = player.interp.nextHeadX < 180 ? 89.9f : 270.1f;
update.HeadX = player.interp.next.HeadX < 180 ? 89.9f : 270.1f;
game.LocalPlayer.SetLocation(update, true);
}
@ -127,7 +127,7 @@ namespace ClassicalSharp {
protected Vector3 GetDirVector() {
return Utils.GetDirVector(player.HeadYRadians,
AdjustPitch(player.HeadX));
AdjustHeadX(player.HeadX));
}
}
@ -187,9 +187,9 @@ namespace ClassicalSharp {
Vector3 camPos = player.EyePosition;
camPos.Y += bobbingVer;
double adjYaw = player.HeadYRadians + Math.PI / 2;
camPos.X += bobbingHor * (float)Math.Sin(adjYaw);
camPos.Z -= bobbingHor * (float)Math.Cos(adjYaw);
double adjHeadY = player.HeadYRadians + Math.PI / 2;
camPos.X += bobbingHor * (float)Math.Sin(adjHeadY);
camPos.Z -= bobbingHor * (float)Math.Cos(adjHeadY);
return camPos;
}
}