move classicalsharp source into sub-directory

This commit is contained in:
UnknownShadow200 2019-02-02 01:44:26 +11:00
parent 01340e8548
commit 767eb71c78
352 changed files with 4175 additions and 3433 deletions

View file

@ -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));
}
}
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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();
}
}
}

View file

@ -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