diff --git a/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs b/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs
index ac3b7a4c8..3de7c0f65 100644
--- a/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs
+++ b/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs
@@ -23,29 +23,31 @@ namespace ClassicalSharp {
}
public void RecalculateSpriteBB( FastBitmap fastBmp ) {
- int elemSize = fastBmp.Width / 16;
for( int i = 0; i < 256; i++ ) {
- if( IsSprite[i] ) {
- int texId = GetTextureLoc( (byte)i, TileSide.Top );
- float topY = GetSpriteBB_TopY( elemSize, texId & 0x0F, texId >> 4, fastBmp );
- float bottomY = GetSpriteBB_BottomY( elemSize, texId & 0x0F, texId >> 4, fastBmp );
- float leftX = GetSpriteBB_LeftX( elemSize, texId & 0x0F, texId >> 4, fastBmp );
- float rightX = GetSpriteBB_RightX( elemSize, texId & 0x0F, texId >> 4, fastBmp );
-
- MinBB[i] = Utils.RotateY( leftX - 0.5f, bottomY, 0, 45f * Utils.Deg2Rad )
- + new Vector3( 0.5f, 0, 0.5f );
- MaxBB[i] = Utils.RotateY( rightX - 0.5f, topY, 0, 45f * Utils.Deg2Rad )
- + new Vector3( 0.5f, 0, 0.5f );
- }
+ if( IsSprite[i] ) RecalculateBB( i, fastBmp );
}
}
+ internal void RecalculateBB( int block, FastBitmap fastBmp ) {
+ int elemSize = fastBmp.Width / 16;
+ int texId = GetTextureLoc( (byte)block, TileSide.Top );
+ float topY = GetSpriteBB_TopY( elemSize, texId & 0x0F, texId >> 4, fastBmp );
+ float bottomY = GetSpriteBB_BottomY( elemSize, texId & 0x0F, texId >> 4, fastBmp );
+ float leftX = GetSpriteBB_LeftX( elemSize, texId & 0x0F, texId >> 4, fastBmp );
+ float rightX = GetSpriteBB_RightX( elemSize, texId & 0x0F, texId >> 4, fastBmp );
+
+ MinBB[block] = Utils.RotateY( leftX - 0.5f, bottomY, 0, 45f * Utils.Deg2Rad )
+ + new Vector3( 0.5f, 0, 0.5f );
+ MaxBB[block] = Utils.RotateY( rightX - 0.5f, topY, 0, 45f * Utils.Deg2Rad )
+ + new Vector3( 0.5f, 0, 0.5f );
+ }
+
const int alphaTest = unchecked( (int)0x80000000 );
unsafe float GetSpriteBB_TopY( int size, int tileX, int tileY, FastBitmap fastBmp ) {
for( int y = 0; y < size; y++ ) {
int* row = fastBmp.GetRowPtr( tileY * size + y ) + (tileX * size);
for( int x = 0; x < size; x++ ) {
- if( (row[x] & alphaTest) != 0 )
+ if( (row[x] & alphaTest) != 0 )
return 1 - (float)y / size;
}
}
@@ -56,7 +58,7 @@ namespace ClassicalSharp {
for( int y = size - 1; y >= 0; y-- ) {
int* row = fastBmp.GetRowPtr( tileY * size + y ) + (tileX * size);
for( int x = 0; x < size; x++ ) {
- if( (row[x] & alphaTest) != 0 )
+ if( (row[x] & alphaTest) != 0 )
return 1 - (float)(y + 1) / size;
}
}
@@ -64,10 +66,10 @@ namespace ClassicalSharp {
}
unsafe float GetSpriteBB_LeftX( int size, int tileX, int tileY, FastBitmap fastBmp ) {
- for( int x = 0; x < size; x++ ) {
+ for( int x = 0; x < size; x++ ) {
for( int y = 0; y < size; y++ ) {
int* row = fastBmp.GetRowPtr( tileY * size + y ) + (tileX * size);
- if( (row[x] & alphaTest) != 0 )
+ if( (row[x] & alphaTest) != 0 )
return (float)x / size;
}
}
@@ -75,10 +77,10 @@ namespace ClassicalSharp {
}
unsafe float GetSpriteBB_RightX( int size, int tileX, int tileY, FastBitmap fastBmp ) {
- for( int x = size - 1; x >= 0; x-- ) {
+ for( int x = size - 1; x >= 0; x-- ) {
for( int y = 0; y < size; y++ ) {
int* row = fastBmp.GetRowPtr( tileY * size + y ) + (tileX * size);
- if( (row[x] & alphaTest) != 0 )
+ if( (row[x] & alphaTest) != 0 )
return (float)(x + 1) / size;
}
}
diff --git a/ClassicalSharp/Blocks/BlockInfo.cs b/ClassicalSharp/Blocks/BlockInfo.cs
index 43bd83782..20317fcbd 100644
--- a/ClassicalSharp/Blocks/BlockInfo.cs
+++ b/ClassicalSharp/Blocks/BlockInfo.cs
@@ -1,4 +1,5 @@
using System;
+using OpenTK;
namespace ClassicalSharp {
@@ -180,6 +181,8 @@ namespace ClassicalSharp {
SpeedMultiplier[id] = 1;
SetAll( 0, (Block)id );
SetupCullingCache();
+ MinBB[id] = Vector3.Zero;
+ MaxBB[id] = Vector3.One;
}
}
diff --git a/ClassicalSharp/Entities/Entity.cs b/ClassicalSharp/Entities/Entity.cs
index 034621525..ddaeffc2e 100644
--- a/ClassicalSharp/Entities/Entity.cs
+++ b/ClassicalSharp/Entities/Entity.cs
@@ -4,6 +4,8 @@ using OpenTK;
namespace ClassicalSharp {
+ /// Contains a model, along with position, velocity, and rotation.
+ /// May also contain other fields and properties.
public abstract class Entity {
public Entity( Game game ) {
@@ -18,26 +20,31 @@ namespace ClassicalSharp {
public Vector3 Position;
public Vector3 Velocity;
public float YawDegrees, PitchDegrees;
- protected float StepSize;
+
protected Game game;
protected BlockInfo info;
+ /// Rotation of the entity horizontally (i.e. looking north or east)
public float YawRadians {
get { return YawDegrees * Utils.Deg2Rad; }
set { YawDegrees = value * Utils.Rad2Deg; }
}
+ /// Rotation of the entity vertically. (i.e. looking up or down)
public float PitchRadians {
get { return PitchDegrees * Utils.Deg2Rad; }
set { PitchDegrees = value * Utils.Rad2Deg; }
}
+ /// Returns the size of the model that is used for collision detection.
public virtual Vector3 CollisionSize {
get { return new Vector3( 8/16f, 28.5f/16f, 8/16f );
//Model.CollisionSize; TODO: for non humanoid models
}
}
+ /// Bounding box of the model that collision detection
+ /// is performed with, in world coordinates.
public virtual BoundingBox CollisionBounds {
get {
Vector3 pos = Position;
@@ -49,12 +56,17 @@ namespace ClassicalSharp {
public abstract void Despawn();
+ /// Renders the entity's model, interpolating between the previous and next state.
public abstract void Render( double deltaTime, float t );
+ /// Determines whether any of the blocks that intersect the
+ /// bounding box of this entity satisfy the given condition.
public bool TouchesAny( Predicate condition ) {
return TouchesAny( CollisionBounds, condition );
}
+ /// Determines whether any of the blocks that intersect the
+ /// given bounding box satisfy the given condition.
public bool TouchesAny( BoundingBox bounds, Predicate condition ) {
Vector3I bbMin = Vector3I.Floor( bounds.Min );
Vector3I bbMax = Vector3I.Floor( bounds.Max );
@@ -64,6 +76,7 @@ namespace ClassicalSharp {
for( int z = bbMin.Z; z <= bbMax.Z; z++ ) {
if( !game.Map.IsValidPos( x, y, z ) ) continue;
byte block = game.Map.GetBlock( x, y, z );
+
if( condition( block ) ) {
float blockHeight = info.Height[block];
Vector3 min = new Vector3( x, y, z ) + info.MinBB[block];
@@ -77,19 +90,27 @@ namespace ClassicalSharp {
return false;
}
- public const float Adjustment = 0.001f;
+ /// Constant offset used to avoid floating point roundoff errors.
+ public const float Adjustment = 0.001f;
+
+ /// Determines whether any of the blocks that intersect the
+ /// bounding box of this entity are lava or still lava.
protected bool TouchesAnyLava() {
- return TouchesAny( CollisionBounds,
+ return TouchesAny( CollisionBounds,
b => b == (byte)Block.Lava || b == (byte)Block.StillLava );
}
+ /// Determines whether any of the blocks that intersect the
+ /// bounding box of this entity are rope.
protected bool TouchesAnyRope() {
- return TouchesAny( CollisionBounds,
+ return TouchesAny( CollisionBounds,
b => b == (byte)Block.Rope );
}
+ /// Determines whether any of the blocks that intersect the
+ /// bounding box of this entity are water or still water.
protected bool TouchesAnyWater() {
- return TouchesAny( CollisionBounds,
+ return TouchesAny( CollisionBounds,
b => b == (byte)Block.Water || b == (byte)Block.StillWater );
}
}
diff --git a/ClassicalSharp/Entities/LocalPlayer.cs b/ClassicalSharp/Entities/LocalPlayer.cs
index 87a025881..f80a91ea9 100644
--- a/ClassicalSharp/Entities/LocalPlayer.cs
+++ b/ClassicalSharp/Entities/LocalPlayer.cs
@@ -16,6 +16,7 @@ namespace ClassicalSharp {
public byte UserType;
bool canSpeed = true, canFly = true, canRespawn = true, canNoclip = true;
+ /// Whether the player has permission to increase its speed beyond the normal walking speed.
public bool CanSpeed {
get { return canSpeed; }
set { canSpeed = value; }
@@ -37,6 +38,8 @@ namespace ClassicalSharp {
}
float jumpVel = 0.42f;
+ /// Returns the height that the client can currently jump up to.
+ /// Note that when speeding is enabled the client is able to jump much further.
public float JumpHeight {
get { return (float)GetMaxHeight( jumpVel ); }
}
@@ -200,6 +203,9 @@ namespace ClassicalSharp {
}
internal bool jumping, speeding, flying, noClip, flyingDown, flyingUp;
+
+ /// Parses hack flags specified in the motd and/or name of the server.
+ /// Recognises +/-hax, +/-fly, +/-noclip, +/-speed, +/-respawn, +/-ophax
public void ParseHackFlags( string name, string motd ) {
string joined = name + motd;
if( joined.Contains( "-hax" ) ) {
@@ -216,9 +222,8 @@ namespace ClassicalSharp {
ParseFlag( b => CanSpeed = b, joined, "speed" );
ParseFlag( b => CanRespawn = b, joined, "respawn" );
- if( UserType == 0x64 ) {
+ if( UserType == 0x64 )
ParseFlag( b => CanFly = CanNoclip = CanRespawn = CanSpeed = b, joined, "ophax" );
- }
}
static void ParseFlag( Action action, string joined, string flag ) {
@@ -229,6 +234,8 @@ namespace ClassicalSharp {
}
}
+ /// Sets the user type of this user. This is used to control permissions for grass,
+ /// bedrock, water and lava blocks on servers that don't support CPE block permissions.
public void SetUserType( byte value ) {
UserType = value;
Inventory inv = game.Inventory;
@@ -244,6 +251,8 @@ namespace ClassicalSharp {
internal Vector3 lastPos, nextPos;
internal float lastYaw, nextYaw, lastPitch, nextPitch;
+
+ /// Linearly interpolates position and rotation between the previous and next state.
public void SetInterpPosition( float t ) {
Position = Vector3.Lerp( lastPos, nextPos, t );
YawDegrees = Utils.LerpAngle( lastYaw, nextYaw, t );
@@ -278,6 +287,8 @@ namespace ClassicalSharp {
}
}
+ /// Calculates the jump velocity required such that when a client presses
+ /// the jump binding they will be able to jump up to the given height.
internal void CalculateJumpVelocity( float jumpHeight ) {
jumpVel = 0;
if( jumpHeight >= 256 ) jumpVel = 10.0f;
diff --git a/ClassicalSharp/Entities/LocationUpdate.cs b/ClassicalSharp/Entities/LocationUpdate.cs
index 7fa674e1c..d2afd3bce 100644
--- a/ClassicalSharp/Entities/LocationUpdate.cs
+++ b/ClassicalSharp/Entities/LocationUpdate.cs
@@ -10,17 +10,25 @@ namespace ClassicalSharp {
public Vector3 Pos;
public float Yaw, Pitch;
+ /// Whether this update includes an absolute or relative position.
public bool IncludesPosition;
+
+ /// Whether the positon is specified as absolute (world coordinates),
+ /// or relative to the last position that was received from the server.
public bool RelativePosition;
+
+ /// Whether this update includes absolute yaw and pitch.
public bool IncludesOrientation;
public LocationUpdate( float x, float y, float z, float yaw, float pitch,
bool incPos, bool relPos, bool incOri ) {
Pos = new Vector3( x, y, z );
+ // Make sure yaw and pitch are in [0, 360)
Yaw = yaw % 360;
if( Yaw < 0 ) Yaw += 360;
Pitch = pitch % 360;
if( Pitch < 0 ) Pitch += 360;
+
IncludesPosition = incPos;
RelativePosition = relPos;
IncludesOrientation = incOri;
diff --git a/ClassicalSharp/Entities/PhysicsEntity.cs b/ClassicalSharp/Entities/PhysicsEntity.cs
index 6f5f024df..19a0f79e3 100644
--- a/ClassicalSharp/Entities/PhysicsEntity.cs
+++ b/ClassicalSharp/Entities/PhysicsEntity.cs
@@ -6,10 +6,12 @@ namespace ClassicalSharp {
/// Entity that performs collision detection.
public abstract class PhysicsEntity : Entity {
-
+
public PhysicsEntity( Game game ) : base( game ) {
}
- protected bool onGround, collideX, collideY, collideZ;
+
+ protected bool onGround, collideX, collideY, collideZ;
+ protected float StepSize;
protected byte GetPhysicsBlockId( int x, int y, int z ) {
if( x < 0 || x >= game.Map.Width || z < 0 ||
diff --git a/ClassicalSharp/Game/ChatLog.cs b/ClassicalSharp/Game/ChatLog.cs
index 29bf5fb80..bef651bb6 100644
--- a/ClassicalSharp/Game/ChatLog.cs
+++ b/ClassicalSharp/Game/ChatLog.cs
@@ -70,7 +70,7 @@ namespace ClassicalSharp {
}
}
- DateTime last = new DateTime( 1, 1, 1 );
+ DateTime last;
StreamWriter writer = null;
void LogChatToFile( string text ) {
DateTime now = DateTime.Now;
diff --git a/ClassicalSharp/Game/Inventory.cs b/ClassicalSharp/Game/Inventory.cs
index 966ddb3d7..f848ec57d 100644
--- a/ClassicalSharp/Game/Inventory.cs
+++ b/ClassicalSharp/Game/Inventory.cs
@@ -2,6 +2,7 @@
namespace ClassicalSharp {
+ /// Contains the hotbar of blocks, as well as the permissions for placing and deleting all blocks.
public sealed class Inventory {
public Inventory( Game game ) {
@@ -29,6 +30,8 @@ namespace ClassicalSharp {
public InventoryPermissions CanPlace = new InventoryPermissions();
public InventoryPermissions CanDelete = new InventoryPermissions();
+ /// Gets or sets the index of the held block.
+ /// Fails if the server has forbidden up from changing the held block.
public int HeldBlockIndex {
get { return hotbarIndex; }
set {
@@ -41,6 +44,8 @@ namespace ClassicalSharp {
}
}
+ /// Gets or sets the block currently held by the player.
+ /// Fails if the server has forbidden up from changing the held block.
public Block HeldBlock {
get { return Hotbar[hotbarIndex]; }
set {
diff --git a/ClassicalSharp/Network/NetworkProcessor.CPE.cs b/ClassicalSharp/Network/NetworkProcessor.CPE.cs
index ba13e35e1..48101ff29 100644
--- a/ClassicalSharp/Network/NetworkProcessor.CPE.cs
+++ b/ClassicalSharp/Network/NetworkProcessor.CPE.cs
@@ -336,6 +336,14 @@ namespace ClassicalSharp {
info.FogColour[block] = new FastColour(
reader.ReadUInt8(), reader.ReadUInt8(), reader.ReadUInt8() );
info.SetupCullingCache();
+
+ // Update sprite BoundingBox if necessary
+ if( info.IsSprite[block] ) {
+ using( FastBitmap fastBmp =
+ new FastBitmap( game.TerrainAtlas.AtlasBitmap, true ) ) {
+ info.RecalculateBB( block, fastBmp );
+ }
+ }
}
void HandleCpeRemoveBlockDefinition() {
diff --git a/ClassicalSharp/Network/Utils/AsyncDownloader.cs b/ClassicalSharp/Network/Utils/AsyncDownloader.cs
index 1da815c3e..46a22b9cb 100644
--- a/ClassicalSharp/Network/Utils/AsyncDownloader.cs
+++ b/ClassicalSharp/Network/Utils/AsyncDownloader.cs
@@ -29,6 +29,9 @@ namespace ClassicalSharp.Network {
worker.Start();
}
+ /// Asynchronously downloads a skin. If 'skinName' points to the url then the skin is
+ /// downloaded from that url, otherwise it is downloaded from the url 'defaultSkinServer'/'skinName'.png
+ /// Identifier is skin_'skinName'.
public void DownloadSkin( string skinName ) {
string strippedSkinName = Utils.StripColours( skinName );
string url = Utils.IsUrl( skinName ) ? skinName :
@@ -36,14 +39,17 @@ namespace ClassicalSharp.Network {
AddRequest( url, true, "skin_" + strippedSkinName, 0 );
}
+ /// Asynchronously downloads a bitmap image from the specified url.
public void DownloadImage( string url, bool priority, string identifier ) {
AddRequest( url, priority, identifier, 0 );
}
+ /// Asynchronously downloads a string from the specified url.
public void DownloadPage( string url, bool priority, string identifier ) {
AddRequest( url, priority, identifier, 1 );
}
+ /// Asynchronously downloads a byte array from the specified url.
public void DownloadData( string url, bool priority, string identifier ) {
AddRequest( url, priority, identifier, 2 );
}
@@ -60,6 +66,10 @@ namespace ClassicalSharp.Network {
handle.Set();
}
+ /// Informs the asynchronous thread that it should stop processing further requests
+ /// and can consequentially exit the for loop.
+ /// Note that this will *block** the calling thread as the method waits until the asynchronous
+ /// thread has exited the for loop.
public void Dispose() {
lock( requestLocker ) {
requests.Insert( 0, null );
@@ -71,6 +81,8 @@ namespace ClassicalSharp.Network {
client.Dispose();
}
+ /// Removes older entries that were downloaded a certain time ago
+ /// but were never removed from the downloaded queue.
public void PurgeOldEntries( int seconds ) {
lock( downloadedLocker ) {
DateTime now = DateTime.UtcNow;
@@ -95,6 +107,10 @@ namespace ClassicalSharp.Network {
}
}
+ /// Returns whether the requested item exists in the downloaded queue.
+ /// If it does, it removes the item from the queue and outputs it.
+ /// If the asynchronous thread failed to download the item, this method
+ /// will return 'true' and 'item' will be set. However, the contents of the 'item' object will be null.
public bool TryGetItem( string identifier, out DownloadedItem item ) {
bool success = false;
lock( downloadedLocker ) {
@@ -167,8 +183,8 @@ namespace ClassicalSharp.Network {
downloaded[request.Identifier] = newItem;
}
}
-
- class GZipWebClient : WebClient {
+
+ sealed class GZipWebClient : WebClient {
protected override WebRequest GetWebRequest( Uri address ) {
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest( address );
@@ -177,7 +193,7 @@ namespace ClassicalSharp.Network {
}
}
- class Request {
+ sealed class Request {
public string Url;
public string Identifier;
@@ -193,10 +209,21 @@ namespace ClassicalSharp.Network {
}
}
+ /// Represents an item that was asynchronously downloaded.
public class DownloadedItem {
+ /// Contents that were downloaded. Can be a bitmap, string or byte array.
public object Data;
- public DateTime TimeAdded, TimeDownloaded;
+
+ /// Instant in time the item was originally added to the download queue.
+ public DateTime TimeAdded;
+
+ /// Instant in time the item was fully downloaded.
+ public DateTime TimeDownloaded;
+
+ ///
+ ///
+ ///
public string Url;
public DownloadedItem( object data, DateTime timeAdded, string url ) {
diff --git a/ClassicalSharp/Rendering/StandardEnvRenderer.cs b/ClassicalSharp/Rendering/StandardEnvRenderer.cs
index 07d827e3e..1810db83b 100644
--- a/ClassicalSharp/Rendering/StandardEnvRenderer.cs
+++ b/ClassicalSharp/Rendering/StandardEnvRenderer.cs
@@ -1,8 +1,6 @@
using System;
-using System.Drawing;
using ClassicalSharp.GraphicsAPI;
using OpenTK;
-using OpenTK;
namespace ClassicalSharp.Renderers {