mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-22 09:01:57 -05:00
move classicalsharp source into sub-directory
This commit is contained in:
parent
01340e8548
commit
767eb71c78
352 changed files with 4175 additions and 3433 deletions
|
@ -1,43 +1,43 @@
|
|||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using ClassicalSharp.Gui.Widgets;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace ClassicalSharp.Gui.Screens {
|
||||
public class DeathScreen : MenuScreen {
|
||||
|
||||
public DeathScreen(Game game) : base(game) {
|
||||
}
|
||||
|
||||
public override void Init() {
|
||||
textFont = new Font(game.FontName, 40);
|
||||
base.Init();
|
||||
ContextRecreated();
|
||||
}
|
||||
|
||||
protected override void ContextRecreated() {
|
||||
string score = game.Chat.Status1.Text;
|
||||
widgets = new Widget[] {
|
||||
TextWidget.Create(game, "Game over!", textFont)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, 0, -150),
|
||||
TextWidget.Create(game, score, titleFont)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, 0, -75),
|
||||
ButtonWidget.Create(game, 400, "Generate new level...", titleFont, GenLevelClick)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, 0, 25),
|
||||
ButtonWidget.Create(game, 400, "Load level...", titleFont, LoadLevelClick)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, 0, 75),
|
||||
};
|
||||
}
|
||||
|
||||
public override bool HandlesKeyDown(Key key) { return true; }
|
||||
|
||||
void GenLevelClick(Game g, Widget w) {
|
||||
game.Gui.SetNewScreen(new GenLevelScreen(game));
|
||||
}
|
||||
|
||||
void LoadLevelClick(Game g, Widget w) {
|
||||
game.Gui.SetNewScreen(new LoadLevelScreen(game));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using ClassicalSharp.Gui.Widgets;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace ClassicalSharp.Gui.Screens {
|
||||
public class DeathScreen : MenuScreen {
|
||||
|
||||
public DeathScreen(Game game) : base(game) {
|
||||
}
|
||||
|
||||
public override void Init() {
|
||||
textFont = new Font(game.FontName, 40);
|
||||
base.Init();
|
||||
ContextRecreated();
|
||||
}
|
||||
|
||||
protected override void ContextRecreated() {
|
||||
string score = game.Chat.Status1.Text;
|
||||
widgets = new Widget[] {
|
||||
TextWidget.Create(game, "Game over!", textFont)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, 0, -150),
|
||||
TextWidget.Create(game, score, titleFont)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, 0, -75),
|
||||
ButtonWidget.Create(game, 400, "Generate new level...", titleFont, GenLevelClick)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, 0, 25),
|
||||
ButtonWidget.Create(game, 400, "Load level...", titleFont, LoadLevelClick)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, 0, 75),
|
||||
};
|
||||
}
|
||||
|
||||
public override bool HandlesKeyDown(Key key) { return true; }
|
||||
|
||||
void GenLevelClick(Game g, Widget w) {
|
||||
game.Gui.SetNewScreen(new GenLevelScreen(game));
|
||||
}
|
||||
|
||||
void LoadLevelClick(Game g, Widget w) {
|
||||
game.Gui.SetNewScreen(new LoadLevelScreen(game));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,180 +1,180 @@
|
|||
// 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 State cur;
|
||||
|
||||
public override void SetLocation(LocationUpdate update, bool interpolate) {
|
||||
State last = cur;
|
||||
byte flags = update.Flags;
|
||||
if ((flags & LocationUpdateFlag.Pos) != 0) {
|
||||
cur.Pos = update.RelativePos ? cur.Pos + update.Pos : update.Pos;
|
||||
}
|
||||
|
||||
if ((flags & LocationUpdateFlag.HeadX) != 0) cur.HeadX = update.HeadX;
|
||||
if ((flags & LocationUpdateFlag.HeadY) != 0) cur.HeadY = update.HeadY;
|
||||
if ((flags & LocationUpdateFlag.RotX) != 0) cur.RotX = update.RotX;
|
||||
if ((flags & LocationUpdateFlag.RotZ) != 0) cur.RotZ = update.RotZ;
|
||||
|
||||
if (!interpolate) {
|
||||
stateCount = 0;
|
||||
next = cur; prev = next;
|
||||
rotYStateCount = 0;
|
||||
nextRotY = prevRotY = cur.HeadY;
|
||||
} else {
|
||||
// Smoother interpolation by also adding midpoint.
|
||||
State mid;
|
||||
mid.Pos = Vector3.Lerp(last.Pos, cur.Pos, 0.5f);
|
||||
mid.RotX = Utils.LerpAngle(last.RotX, cur.RotX, 0.5f);
|
||||
mid.RotZ = Utils.LerpAngle(last.RotZ, cur.RotZ, 0.5f);
|
||||
mid.HeadX = Utils.LerpAngle(last.HeadX, cur.HeadX, 0.5f);
|
||||
mid.HeadY = Utils.LerpAngle(last.HeadY, cur.HeadY, 0.5f);
|
||||
AddState(mid); AddState(cur);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
AddRotY(Utils.LerpAngle(last.HeadY, cur.HeadY, (i + 1) / 3f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void AdvanceState() {
|
||||
prev = next;
|
||||
if (stateCount > 0) {
|
||||
next = states[0];
|
||||
RemoveOldest(states, ref stateCount);
|
||||
}
|
||||
base.AdvanceState();
|
||||
}
|
||||
|
||||
State[] states = new State[10];
|
||||
int stateCount;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void Angle(ref float prev, ref float next, float value, bool interpolate) {
|
||||
next = value;
|
||||
if (!interpolate) prev = value;
|
||||
}
|
||||
|
||||
public override void SetLocation(LocationUpdate update, bool interpolate) {
|
||||
byte flags = update.Flags;
|
||||
if ((flags & LocationUpdateFlag.Pos) != 0) {
|
||||
next.Pos = update.RelativePos ? next.Pos + update.Pos : update.Pos;
|
||||
// If server sets Y position exactly on ground, push up a tiny bit
|
||||
float yOffset = next.Pos.Y - Utils.Floor(next.Pos.Y);
|
||||
if (yOffset < Entity.Adjustment) { next.Pos.Y += Entity.Adjustment; }
|
||||
if (!interpolate) { prev.Pos = next.Pos; entity.Position = next.Pos; }
|
||||
}
|
||||
|
||||
if ((flags & LocationUpdateFlag.HeadX) != 0) {
|
||||
Angle(ref prev.HeadX, ref next.HeadX, update.HeadX, interpolate);
|
||||
}
|
||||
if ((flags & LocationUpdateFlag.HeadY) != 0) {
|
||||
Angle(ref prev.HeadY, ref next.HeadY, update.HeadY, interpolate);
|
||||
}
|
||||
if ((flags & LocationUpdateFlag.RotX) != 0) {
|
||||
Angle(ref prev.RotX, ref next.RotX, update.RotX, interpolate);
|
||||
}
|
||||
if ((flags & LocationUpdateFlag.RotZ) != 0) {
|
||||
Angle(ref prev.RotZ, ref next.RotZ, update.RotZ, interpolate);
|
||||
}
|
||||
|
||||
if ((flags & LocationUpdateFlag.HeadY) != 0) {
|
||||
// Body Y rotation lags slightly behind
|
||||
if (!interpolate) {
|
||||
nextRotY = update.HeadY; entity.RotY = update.HeadY;
|
||||
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();
|
||||
}
|
||||
}
|
||||
// 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 State cur;
|
||||
|
||||
public override void SetLocation(LocationUpdate update, bool interpolate) {
|
||||
State last = cur;
|
||||
byte flags = update.Flags;
|
||||
if ((flags & LocationUpdateFlag.Pos) != 0) {
|
||||
cur.Pos = update.RelativePos ? cur.Pos + update.Pos : update.Pos;
|
||||
}
|
||||
|
||||
if ((flags & LocationUpdateFlag.HeadX) != 0) cur.HeadX = update.HeadX;
|
||||
if ((flags & LocationUpdateFlag.HeadY) != 0) cur.HeadY = update.HeadY;
|
||||
if ((flags & LocationUpdateFlag.RotX) != 0) cur.RotX = update.RotX;
|
||||
if ((flags & LocationUpdateFlag.RotZ) != 0) cur.RotZ = update.RotZ;
|
||||
|
||||
if (!interpolate) {
|
||||
stateCount = 0;
|
||||
next = cur; prev = next;
|
||||
rotYStateCount = 0;
|
||||
nextRotY = prevRotY = cur.HeadY;
|
||||
} else {
|
||||
// Smoother interpolation by also adding midpoint.
|
||||
State mid;
|
||||
mid.Pos = Vector3.Lerp(last.Pos, cur.Pos, 0.5f);
|
||||
mid.RotX = Utils.LerpAngle(last.RotX, cur.RotX, 0.5f);
|
||||
mid.RotZ = Utils.LerpAngle(last.RotZ, cur.RotZ, 0.5f);
|
||||
mid.HeadX = Utils.LerpAngle(last.HeadX, cur.HeadX, 0.5f);
|
||||
mid.HeadY = Utils.LerpAngle(last.HeadY, cur.HeadY, 0.5f);
|
||||
AddState(mid); AddState(cur);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
AddRotY(Utils.LerpAngle(last.HeadY, cur.HeadY, (i + 1) / 3f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void AdvanceState() {
|
||||
prev = next;
|
||||
if (stateCount > 0) {
|
||||
next = states[0];
|
||||
RemoveOldest(states, ref stateCount);
|
||||
}
|
||||
base.AdvanceState();
|
||||
}
|
||||
|
||||
State[] states = new State[10];
|
||||
int stateCount;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void Angle(ref float prev, ref float next, float value, bool interpolate) {
|
||||
next = value;
|
||||
if (!interpolate) prev = value;
|
||||
}
|
||||
|
||||
public override void SetLocation(LocationUpdate update, bool interpolate) {
|
||||
byte flags = update.Flags;
|
||||
if ((flags & LocationUpdateFlag.Pos) != 0) {
|
||||
next.Pos = update.RelativePos ? next.Pos + update.Pos : update.Pos;
|
||||
// If server sets Y position exactly on ground, push up a tiny bit
|
||||
float yOffset = next.Pos.Y - Utils.Floor(next.Pos.Y);
|
||||
if (yOffset < Entity.Adjustment) { next.Pos.Y += Entity.Adjustment; }
|
||||
if (!interpolate) { prev.Pos = next.Pos; entity.Position = next.Pos; }
|
||||
}
|
||||
|
||||
if ((flags & LocationUpdateFlag.HeadX) != 0) {
|
||||
Angle(ref prev.HeadX, ref next.HeadX, update.HeadX, interpolate);
|
||||
}
|
||||
if ((flags & LocationUpdateFlag.HeadY) != 0) {
|
||||
Angle(ref prev.HeadY, ref next.HeadY, update.HeadY, interpolate);
|
||||
}
|
||||
if ((flags & LocationUpdateFlag.RotX) != 0) {
|
||||
Angle(ref prev.RotX, ref next.RotX, update.RotX, interpolate);
|
||||
}
|
||||
if ((flags & LocationUpdateFlag.RotZ) != 0) {
|
||||
Angle(ref prev.RotZ, ref next.RotZ, update.RotZ, interpolate);
|
||||
}
|
||||
|
||||
if ((flags & LocationUpdateFlag.HeadY) != 0) {
|
||||
// Body Y rotation lags slightly behind
|
||||
if (!interpolate) {
|
||||
nextRotY = update.HeadY; entity.RotY = update.HeadY;
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,103 +1,103 @@
|
|||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
using System;
|
||||
using ClassicalSharp.Physics;
|
||||
using OpenTK;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace ClassicalSharp.Entities {
|
||||
|
||||
/// <summary> Entity component that plays block step sounds. </summary>
|
||||
public sealed class SoundComponent {
|
||||
|
||||
LocalPlayer p;
|
||||
Game game;
|
||||
Predicate<BlockID> checkSoundNonSolid, checkSoundSolid;
|
||||
|
||||
public SoundComponent(Game game, Entity entity) {
|
||||
this.game = game;
|
||||
p = (LocalPlayer)entity;
|
||||
checkSoundNonSolid = CheckSoundNonSolid;
|
||||
checkSoundSolid = CheckSoundSolid;
|
||||
lastSoundPos = -Utils.MaxPos();
|
||||
}
|
||||
|
||||
Vector3 lastSoundPos;
|
||||
public void Tick(bool wasOnGround) {
|
||||
Vector3 soundPos = p.interp.next.Pos;
|
||||
GetSound();
|
||||
if (!anyNonAir) soundPos = Utils.MaxPos();
|
||||
|
||||
if (p.onGround && (DoPlaySound(soundPos) || !wasOnGround)) {
|
||||
game.AudioPlayer.PlayStepSound(sndType);
|
||||
lastSoundPos = soundPos;
|
||||
}
|
||||
}
|
||||
|
||||
bool DoPlaySound(Vector3 soundPos) {
|
||||
float distSq = (lastSoundPos - soundPos).LengthSquared;
|
||||
bool enoughDist = distSq > 1.75f * 1.75f;
|
||||
// just play every certain block interval when not animating
|
||||
if (p.anim.swing < 0.999f) return enoughDist;
|
||||
|
||||
// have our legs just crossed over the '0' point?
|
||||
float oldLegRot, newLegRot;
|
||||
if (game.Camera.IsThirdPerson) {
|
||||
oldLegRot = (float)Math.Cos(p.anim.walkTimeO);
|
||||
newLegRot = (float)Math.Cos(p.anim.walkTimeN);
|
||||
} else {
|
||||
oldLegRot = (float)Math.Sin(p.anim.walkTimeO);
|
||||
newLegRot = (float)Math.Sin(p.anim.walkTimeN);
|
||||
}
|
||||
return Math.Sign(oldLegRot) != Math.Sign(newLegRot);
|
||||
}
|
||||
|
||||
bool anyNonAir = false;
|
||||
byte sndType = SoundType.None;
|
||||
void GetSound() {
|
||||
Vector3 pos = p.interp.next.Pos;
|
||||
AABB bounds = p.Bounds;
|
||||
sndType = SoundType.None;
|
||||
anyNonAir = false;
|
||||
|
||||
// first check surrounding liquids/gas for sounds
|
||||
p.TouchesAny(bounds, checkSoundNonSolid);
|
||||
if (sndType != SoundType.None) return;
|
||||
|
||||
// then check block standing on
|
||||
pos.Y -= 0.01f;
|
||||
Vector3I feetPos = Vector3I.Floor(pos);
|
||||
BlockID blockUnder = game.World.SafeGetBlock(feetPos);
|
||||
float maxY = feetPos.Y + BlockInfo.MaxBB[blockUnder].Y;
|
||||
|
||||
byte typeUnder = BlockInfo.StepSounds[blockUnder];
|
||||
byte collideUnder = BlockInfo.Collide[blockUnder];
|
||||
if (maxY >= pos.Y && collideUnder == CollideType.Solid && typeUnder != SoundType.None) {
|
||||
anyNonAir = true; sndType = typeUnder; return;
|
||||
}
|
||||
|
||||
// then check all solid blocks at feet
|
||||
bounds.Max.Y = bounds.Min.Y = pos.Y;
|
||||
p.TouchesAny(bounds, checkSoundSolid);
|
||||
}
|
||||
|
||||
bool CheckSoundNonSolid(BlockID b) {
|
||||
byte newType = BlockInfo.StepSounds[b];
|
||||
byte collide = BlockInfo.Collide[b];
|
||||
if (newType != SoundType.None && collide != CollideType.Solid)
|
||||
sndType = newType;
|
||||
|
||||
if (BlockInfo.Draw[b] != DrawType.Gas)
|
||||
anyNonAir = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckSoundSolid(BlockID b) {
|
||||
byte newType = BlockInfo.StepSounds[b];
|
||||
if (newType != SoundType.None) sndType = newType;
|
||||
|
||||
if (BlockInfo.Draw[b] != DrawType.Gas)
|
||||
anyNonAir = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
using System;
|
||||
using ClassicalSharp.Physics;
|
||||
using OpenTK;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace ClassicalSharp.Entities {
|
||||
|
||||
/// <summary> Entity component that plays block step sounds. </summary>
|
||||
public sealed class SoundComponent {
|
||||
|
||||
LocalPlayer p;
|
||||
Game game;
|
||||
Predicate<BlockID> checkSoundNonSolid, checkSoundSolid;
|
||||
|
||||
public SoundComponent(Game game, Entity entity) {
|
||||
this.game = game;
|
||||
p = (LocalPlayer)entity;
|
||||
checkSoundNonSolid = CheckSoundNonSolid;
|
||||
checkSoundSolid = CheckSoundSolid;
|
||||
lastSoundPos = -Utils.MaxPos();
|
||||
}
|
||||
|
||||
Vector3 lastSoundPos;
|
||||
public void Tick(bool wasOnGround) {
|
||||
Vector3 soundPos = p.interp.next.Pos;
|
||||
GetSound();
|
||||
if (!anyNonAir) soundPos = Utils.MaxPos();
|
||||
|
||||
if (p.onGround && (DoPlaySound(soundPos) || !wasOnGround)) {
|
||||
game.AudioPlayer.PlayStepSound(sndType);
|
||||
lastSoundPos = soundPos;
|
||||
}
|
||||
}
|
||||
|
||||
bool DoPlaySound(Vector3 soundPos) {
|
||||
float distSq = (lastSoundPos - soundPos).LengthSquared;
|
||||
bool enoughDist = distSq > 1.75f * 1.75f;
|
||||
// just play every certain block interval when not animating
|
||||
if (p.anim.swing < 0.999f) return enoughDist;
|
||||
|
||||
// have our legs just crossed over the '0' point?
|
||||
float oldLegRot, newLegRot;
|
||||
if (game.Camera.IsThirdPerson) {
|
||||
oldLegRot = (float)Math.Cos(p.anim.walkTimeO);
|
||||
newLegRot = (float)Math.Cos(p.anim.walkTimeN);
|
||||
} else {
|
||||
oldLegRot = (float)Math.Sin(p.anim.walkTimeO);
|
||||
newLegRot = (float)Math.Sin(p.anim.walkTimeN);
|
||||
}
|
||||
return Math.Sign(oldLegRot) != Math.Sign(newLegRot);
|
||||
}
|
||||
|
||||
bool anyNonAir = false;
|
||||
byte sndType = SoundType.None;
|
||||
void GetSound() {
|
||||
Vector3 pos = p.interp.next.Pos;
|
||||
AABB bounds = p.Bounds;
|
||||
sndType = SoundType.None;
|
||||
anyNonAir = false;
|
||||
|
||||
// first check surrounding liquids/gas for sounds
|
||||
p.TouchesAny(bounds, checkSoundNonSolid);
|
||||
if (sndType != SoundType.None) return;
|
||||
|
||||
// then check block standing on
|
||||
pos.Y -= 0.01f;
|
||||
Vector3I feetPos = Vector3I.Floor(pos);
|
||||
BlockID blockUnder = game.World.SafeGetBlock(feetPos);
|
||||
float maxY = feetPos.Y + BlockInfo.MaxBB[blockUnder].Y;
|
||||
|
||||
byte typeUnder = BlockInfo.StepSounds[blockUnder];
|
||||
byte collideUnder = BlockInfo.Collide[blockUnder];
|
||||
if (maxY >= pos.Y && collideUnder == CollideType.Solid && typeUnder != SoundType.None) {
|
||||
anyNonAir = true; sndType = typeUnder; return;
|
||||
}
|
||||
|
||||
// then check all solid blocks at feet
|
||||
bounds.Max.Y = bounds.Min.Y = pos.Y;
|
||||
p.TouchesAny(bounds, checkSoundSolid);
|
||||
}
|
||||
|
||||
bool CheckSoundNonSolid(BlockID b) {
|
||||
byte newType = BlockInfo.StepSounds[b];
|
||||
byte collide = BlockInfo.Collide[b];
|
||||
if (newType != SoundType.None && collide != CollideType.Solid)
|
||||
sndType = newType;
|
||||
|
||||
if (BlockInfo.Draw[b] != DrawType.Gas)
|
||||
anyNonAir = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckSoundSolid(BlockID b) {
|
||||
byte newType = BlockInfo.StepSounds[b];
|
||||
if (newType != SoundType.None) sndType = newType;
|
||||
|
||||
if (BlockInfo.Draw[b] != DrawType.Gas)
|
||||
anyNonAir = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,84 +1,84 @@
|
|||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
#if SURVIVAL_TEST
|
||||
using System;
|
||||
using OpenTK;
|
||||
|
||||
namespace ClassicalSharp.Entities.Mobs {
|
||||
|
||||
public abstract class AI {
|
||||
|
||||
protected Game game;
|
||||
protected Entity entity;
|
||||
static Random random = new Random();
|
||||
|
||||
public Vector3 MoveVelocity;
|
||||
|
||||
public AI(Game game, Entity entity) {
|
||||
this.game = game;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public abstract void Tick(Entity target);
|
||||
|
||||
public abstract void AttackedBy(Entity source);
|
||||
|
||||
|
||||
int randomCount;
|
||||
Vector3 randomDir;
|
||||
protected void MoveRandomly(Entity source) {
|
||||
// Move in new direction
|
||||
if (randomCount == 0) {
|
||||
randomDir.X = (float)(random.NextDouble() - 0.5);
|
||||
randomDir.Z = (float)(random.NextDouble() - 0.5);
|
||||
}
|
||||
|
||||
randomCount = (randomCount + 1) & 0x1F;
|
||||
MoveInDirection(source, randomDir);
|
||||
}
|
||||
|
||||
protected void MoveInDirection(Entity source, Vector3 dir) {
|
||||
double rotYRadians, headXRadians;
|
||||
Utils.GetHeading(dir, out rotYRadians, out headXRadians);
|
||||
|
||||
float rotY = (float)(rotYRadians * Utils.Rad2Deg);
|
||||
float headX = (float)(headXRadians * Utils.Rad2Deg);
|
||||
LocationUpdate update = LocationUpdate.MakeOri(rotY, headX);
|
||||
source.SetLocation(update, false);
|
||||
MoveVelocity = dir * 0.9f;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FleeAI : AI {
|
||||
|
||||
public FleeAI(Game game, Entity entity) : base(game, entity) { }
|
||||
|
||||
public override void Tick(Entity target) {
|
||||
MoveRandomly(entity);
|
||||
}
|
||||
|
||||
public override void AttackedBy(Entity source) {
|
||||
Vector3 fleeDir = -Vector3.Normalize(source.Position - entity.Position);
|
||||
MoveInDirection(source, fleeDir * 5);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HostileAI : AI {
|
||||
|
||||
public HostileAI(Game game, Entity entity) : base(game, entity) { }
|
||||
|
||||
public override void Tick(Entity target) {
|
||||
float distSq = (target.Position - entity.Position).LengthSquared;
|
||||
if (distSq > 16 * 16) {
|
||||
MoveRandomly(entity);
|
||||
} else {
|
||||
Vector3 dir = Vector3.Normalize(target.Position - entity.Position);
|
||||
dir.Y = 0;
|
||||
MoveInDirection(entity, dir);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AttackedBy(Entity source) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
#if SURVIVAL_TEST
|
||||
using System;
|
||||
using OpenTK;
|
||||
|
||||
namespace ClassicalSharp.Entities.Mobs {
|
||||
|
||||
public abstract class AI {
|
||||
|
||||
protected Game game;
|
||||
protected Entity entity;
|
||||
static Random random = new Random();
|
||||
|
||||
public Vector3 MoveVelocity;
|
||||
|
||||
public AI(Game game, Entity entity) {
|
||||
this.game = game;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public abstract void Tick(Entity target);
|
||||
|
||||
public abstract void AttackedBy(Entity source);
|
||||
|
||||
|
||||
int randomCount;
|
||||
Vector3 randomDir;
|
||||
protected void MoveRandomly(Entity source) {
|
||||
// Move in new direction
|
||||
if (randomCount == 0) {
|
||||
randomDir.X = (float)(random.NextDouble() - 0.5);
|
||||
randomDir.Z = (float)(random.NextDouble() - 0.5);
|
||||
}
|
||||
|
||||
randomCount = (randomCount + 1) & 0x1F;
|
||||
MoveInDirection(source, randomDir);
|
||||
}
|
||||
|
||||
protected void MoveInDirection(Entity source, Vector3 dir) {
|
||||
double rotYRadians, headXRadians;
|
||||
Utils.GetHeading(dir, out rotYRadians, out headXRadians);
|
||||
|
||||
float rotY = (float)(rotYRadians * Utils.Rad2Deg);
|
||||
float headX = (float)(headXRadians * Utils.Rad2Deg);
|
||||
LocationUpdate update = LocationUpdate.MakeOri(rotY, headX);
|
||||
source.SetLocation(update, false);
|
||||
MoveVelocity = dir * 0.9f;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FleeAI : AI {
|
||||
|
||||
public FleeAI(Game game, Entity entity) : base(game, entity) { }
|
||||
|
||||
public override void Tick(Entity target) {
|
||||
MoveRandomly(entity);
|
||||
}
|
||||
|
||||
public override void AttackedBy(Entity source) {
|
||||
Vector3 fleeDir = -Vector3.Normalize(source.Position - entity.Position);
|
||||
MoveInDirection(source, fleeDir * 5);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HostileAI : AI {
|
||||
|
||||
public HostileAI(Game game, Entity entity) : base(game, entity) { }
|
||||
|
||||
public override void Tick(Entity target) {
|
||||
float distSq = (target.Position - entity.Position).LengthSquared;
|
||||
if (distSq > 16 * 16) {
|
||||
MoveRandomly(entity);
|
||||
} else {
|
||||
Vector3 dir = Vector3.Normalize(target.Position - entity.Position);
|
||||
dir.Y = 0;
|
||||
MoveInDirection(entity, dir);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AttackedBy(Entity source) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,45 +1,45 @@
|
|||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
using System;
|
||||
using ClassicalSharp.Model;
|
||||
using OpenTK;
|
||||
|
||||
namespace ClassicalSharp.Entities {
|
||||
|
||||
public sealed class NetPlayer : Player {
|
||||
|
||||
NetInterpComponent interp;
|
||||
public NetPlayer(string displayName, string skinName, Game game) : base(game) {
|
||||
DisplayName = displayName;
|
||||
SkinName = skinName;
|
||||
interp = new NetInterpComponent(game, this);
|
||||
}
|
||||
|
||||
public override void SetLocation(LocationUpdate update, bool interpolate) {
|
||||
interp.SetLocation(update, interpolate);
|
||||
}
|
||||
|
||||
public override void Tick(double delta) {
|
||||
CheckSkin();
|
||||
tickCount++;
|
||||
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.prev.Pos, interp.next.Pos, t);
|
||||
interp.LerpAngles(t);
|
||||
|
||||
anim.GetCurrentAnimState(t);
|
||||
shouldRender = IModel.ShouldRender(this, game.Culling);
|
||||
if (shouldRender) Model.Render(this);
|
||||
}
|
||||
|
||||
public override void RenderName() {
|
||||
if (!shouldRender) return;
|
||||
float dist = IModel.RenderDistance(this, game.CurrentCameraPos);
|
||||
float threshold = game.Entities.NamesMode == NameMode.AllUnscaled ? 8192 * 8192 : 32 * 32;
|
||||
if (dist <= threshold) DrawName();
|
||||
}
|
||||
}
|
||||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
using System;
|
||||
using ClassicalSharp.Model;
|
||||
using OpenTK;
|
||||
|
||||
namespace ClassicalSharp.Entities {
|
||||
|
||||
public sealed class NetPlayer : Player {
|
||||
|
||||
NetInterpComponent interp;
|
||||
public NetPlayer(string displayName, string skinName, Game game) : base(game) {
|
||||
DisplayName = displayName;
|
||||
SkinName = skinName;
|
||||
interp = new NetInterpComponent(game, this);
|
||||
}
|
||||
|
||||
public override void SetLocation(LocationUpdate update, bool interpolate) {
|
||||
interp.SetLocation(update, interpolate);
|
||||
}
|
||||
|
||||
public override void Tick(double delta) {
|
||||
CheckSkin();
|
||||
tickCount++;
|
||||
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.prev.Pos, interp.next.Pos, t);
|
||||
interp.LerpAngles(t);
|
||||
|
||||
anim.GetCurrentAnimState(t);
|
||||
shouldRender = IModel.ShouldRender(this, game.Culling);
|
||||
if (shouldRender) Model.Render(this);
|
||||
}
|
||||
|
||||
public override void RenderName() {
|
||||
if (!shouldRender) return;
|
||||
float dist = IModel.RenderDistance(this, game.CurrentCameraPos);
|
||||
float threshold = game.Entities.NamesMode == NameMode.AllUnscaled ? 8192 * 8192 : 32 * 32;
|
||||
if (dist <= threshold) DrawName();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,41 +1,41 @@
|
|||
using System;
|
||||
|
||||
namespace ClassicalSharp.Entities {
|
||||
|
||||
public sealed class TabList : IGameComponent {
|
||||
public static TabListEntry[] Entries = new TabListEntry[256];
|
||||
|
||||
void IGameComponent.Init(Game game) { }
|
||||
void IGameComponent.Ready(Game game) { }
|
||||
void IGameComponent.OnNewMapLoaded(Game game) { }
|
||||
void IDisposable.Dispose() { }
|
||||
void IGameComponent.OnNewMap(Game game) { }
|
||||
|
||||
void IGameComponent.Reset(Game game) {
|
||||
for (int i = 0; i < Entries.Length; i++)
|
||||
Entries[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TabListEntry {
|
||||
/// <summary> Plain name of the player for autocompletion, etc. </summary>
|
||||
public string PlayerName;
|
||||
/// <summary> Formatted name for display in the player list. </summary>
|
||||
public string ListName;
|
||||
public string ListNameColourless;
|
||||
/// <summary> Name of the group this player is in. </summary>
|
||||
public string Group;
|
||||
/// <summary> Player's rank within the group. (0 is highest) </summary>
|
||||
/// <remarks> Multiple players can share the same rank, so this is not a unique identifier. </remarks>
|
||||
public byte GroupRank;
|
||||
|
||||
public TabListEntry(string playerName, string listName,
|
||||
string groupName, byte groupRank) {
|
||||
PlayerName = Utils.StripColours(playerName);
|
||||
ListName = listName;
|
||||
ListNameColourless = Utils.StripColours(listName);
|
||||
Group = groupName;
|
||||
GroupRank = groupRank;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace ClassicalSharp.Entities {
|
||||
|
||||
public sealed class TabList : IGameComponent {
|
||||
public static TabListEntry[] Entries = new TabListEntry[256];
|
||||
|
||||
void IGameComponent.Init(Game game) { }
|
||||
void IGameComponent.Ready(Game game) { }
|
||||
void IGameComponent.OnNewMapLoaded(Game game) { }
|
||||
void IDisposable.Dispose() { }
|
||||
void IGameComponent.OnNewMap(Game game) { }
|
||||
|
||||
void IGameComponent.Reset(Game game) {
|
||||
for (int i = 0; i < Entries.Length; i++)
|
||||
Entries[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TabListEntry {
|
||||
/// <summary> Plain name of the player for autocompletion, etc. </summary>
|
||||
public string PlayerName;
|
||||
/// <summary> Formatted name for display in the player list. </summary>
|
||||
public string ListName;
|
||||
public string ListNameColourless;
|
||||
/// <summary> Name of the group this player is in. </summary>
|
||||
public string Group;
|
||||
/// <summary> Player's rank within the group. (0 is highest) </summary>
|
||||
/// <remarks> Multiple players can share the same rank, so this is not a unique identifier. </remarks>
|
||||
public byte GroupRank;
|
||||
|
||||
public TabListEntry(string playerName, string listName,
|
||||
string groupName, byte groupRank) {
|
||||
PlayerName = Utils.StripColours(playerName);
|
||||
ListName = listName;
|
||||
ListNameColourless = Utils.StripColours(listName);
|
||||
Group = groupName;
|
||||
GroupRank = groupRank;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue