More comments.

This commit is contained in:
UnknownShadow200 2015-10-24 15:31:57 +11:00
parent fc4e8c7e56
commit a6f90acf00
11 changed files with 120 additions and 35 deletions

View file

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

View file

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

View file

@ -4,6 +4,8 @@ using OpenTK;
namespace ClassicalSharp {
/// <summary> Contains a model, along with position, velocity, and rotation.
/// May also contain other fields and properties. </summary>
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;
/// <summary> Rotation of the entity horizontally (i.e. looking north or east) </summary>
public float YawRadians {
get { return YawDegrees * Utils.Deg2Rad; }
set { YawDegrees = value * Utils.Rad2Deg; }
}
/// <summary> Rotation of the entity vertically. (i.e. looking up or down) </summary>
public float PitchRadians {
get { return PitchDegrees * Utils.Deg2Rad; }
set { PitchDegrees = value * Utils.Rad2Deg; }
}
/// <summary> Returns the size of the model that is used for collision detection. </summary>
public virtual Vector3 CollisionSize {
get { return new Vector3( 8/16f, 28.5f/16f, 8/16f );
//Model.CollisionSize; TODO: for non humanoid models
}
}
/// <summary> Bounding box of the model that collision detection
/// is performed with, in world coordinates. </summary>
public virtual BoundingBox CollisionBounds {
get {
Vector3 pos = Position;
@ -49,12 +56,17 @@ namespace ClassicalSharp {
public abstract void Despawn();
/// <summary> Renders the entity's model, interpolating between the previous and next state. </summary>
public abstract void Render( double deltaTime, float t );
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity satisfy the given condition. </summary>
public bool TouchesAny( Predicate<byte> condition ) {
return TouchesAny( CollisionBounds, condition );
}
/// <summary> Determines whether any of the blocks that intersect the
/// given bounding box satisfy the given condition. </summary>
public bool TouchesAny( BoundingBox bounds, Predicate<byte> 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;
/// <summary> Constant offset used to avoid floating point roundoff errors. </summary>
public const float Adjustment = 0.001f;
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are lava or still lava. </summary>
protected bool TouchesAnyLava() {
return TouchesAny( CollisionBounds,
return TouchesAny( CollisionBounds,
b => b == (byte)Block.Lava || b == (byte)Block.StillLava );
}
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are rope. </summary>
protected bool TouchesAnyRope() {
return TouchesAny( CollisionBounds,
return TouchesAny( CollisionBounds,
b => b == (byte)Block.Rope );
}
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are water or still water. </summary>
protected bool TouchesAnyWater() {
return TouchesAny( CollisionBounds,
return TouchesAny( CollisionBounds,
b => b == (byte)Block.Water || b == (byte)Block.StillWater );
}
}

View file

@ -16,6 +16,7 @@ namespace ClassicalSharp {
public byte UserType;
bool canSpeed = true, canFly = true, canRespawn = true, canNoclip = true;
/// <summary> Whether the player has permission to increase its speed beyond the normal walking speed. </summary>
public bool CanSpeed {
get { return canSpeed; }
set { canSpeed = value; }
@ -37,6 +38,8 @@ namespace ClassicalSharp {
}
float jumpVel = 0.42f;
/// <summary> Returns the height that the client can currently jump up to.<br/>
/// Note that when speeding is enabled the client is able to jump much further. </summary>
public float JumpHeight {
get { return (float)GetMaxHeight( jumpVel ); }
}
@ -200,6 +203,9 @@ namespace ClassicalSharp {
}
internal bool jumping, speeding, flying, noClip, flyingDown, flyingUp;
/// <summary> Parses hack flags specified in the motd and/or name of the server. </summary>
/// <remarks> Recognises +/-hax, +/-fly, +/-noclip, +/-speed, +/-respawn, +/-ophax </remarks>
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<bool> action, string joined, string flag ) {
@ -229,6 +234,8 @@ namespace ClassicalSharp {
}
}
/// <summary> 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. </summary>
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;
/// <summary> Linearly interpolates position and rotation between the previous and next state. </summary>
public void SetInterpPosition( float t ) {
Position = Vector3.Lerp( lastPos, nextPos, t );
YawDegrees = Utils.LerpAngle( lastYaw, nextYaw, t );
@ -278,6 +287,8 @@ namespace ClassicalSharp {
}
}
/// <summary> 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. </summary>
internal void CalculateJumpVelocity( float jumpHeight ) {
jumpVel = 0;
if( jumpHeight >= 256 ) jumpVel = 10.0f;

View file

@ -10,17 +10,25 @@ namespace ClassicalSharp {
public Vector3 Pos;
public float Yaw, Pitch;
/// <summary> Whether this update includes an absolute or relative position. </summary>
public bool IncludesPosition;
/// <summary> Whether the positon is specified as absolute (world coordinates),
/// or relative to the last position that was received from the server. </summary>
public bool RelativePosition;
/// <summary> Whether this update includes absolute yaw and pitch. </summary>
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;

View file

@ -6,10 +6,12 @@ namespace ClassicalSharp {
/// <summary> Entity that performs collision detection. </summary>
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 ||

View file

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

View file

@ -2,6 +2,7 @@
namespace ClassicalSharp {
/// <summary> Contains the hotbar of blocks, as well as the permissions for placing and deleting all blocks. </summary>
public sealed class Inventory {
public Inventory( Game game ) {
@ -29,6 +30,8 @@ namespace ClassicalSharp {
public InventoryPermissions CanPlace = new InventoryPermissions();
public InventoryPermissions CanDelete = new InventoryPermissions();
/// <summary> Gets or sets the index of the held block.
/// Fails if the server has forbidden up from changing the held block. </summary>
public int HeldBlockIndex {
get { return hotbarIndex; }
set {
@ -41,6 +44,8 @@ namespace ClassicalSharp {
}
}
/// <summary> Gets or sets the block currently held by the player.
/// Fails if the server has forbidden up from changing the held block. </summary>
public Block HeldBlock {
get { return Hotbar[hotbarIndex]; }
set {

View file

@ -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() {

View file

@ -29,6 +29,9 @@ namespace ClassicalSharp.Network {
worker.Start();
}
/// <summary> 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 </summary>
/// <remarks> Identifier is skin_'skinName'.</remarks>
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 );
}
/// <summary> Asynchronously downloads a bitmap image from the specified url. </summary>
public void DownloadImage( string url, bool priority, string identifier ) {
AddRequest( url, priority, identifier, 0 );
}
/// <summary> Asynchronously downloads a string from the specified url. </summary>
public void DownloadPage( string url, bool priority, string identifier ) {
AddRequest( url, priority, identifier, 1 );
}
/// <summary> Asynchronously downloads a byte array from the specified url. </summary>
public void DownloadData( string url, bool priority, string identifier ) {
AddRequest( url, priority, identifier, 2 );
}
@ -60,6 +66,10 @@ namespace ClassicalSharp.Network {
handle.Set();
}
/// <summary> Informs the asynchronous thread that it should stop processing further requests
/// and can consequentially exit the for loop.<br/>
/// Note that this will *block** the calling thread as the method waits until the asynchronous
/// thread has exited the for loop. </summary>
public void Dispose() {
lock( requestLocker ) {
requests.Insert( 0, null );
@ -71,6 +81,8 @@ namespace ClassicalSharp.Network {
client.Dispose();
}
/// <summary> Removes older entries that were downloaded a certain time ago
/// but were never removed from the downloaded queue. </summary>
public void PurgeOldEntries( int seconds ) {
lock( downloadedLocker ) {
DateTime now = DateTime.UtcNow;
@ -95,6 +107,10 @@ namespace ClassicalSharp.Network {
}
}
/// <summary> Returns whether the requested item exists in the downloaded queue.
/// If it does, it removes the item from the queue and outputs it. </summary>
/// <remarks> 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.</remarks>
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 {
}
}
/// <summary> Represents an item that was asynchronously downloaded. </summary>
public class DownloadedItem {
/// <summary> Contents that were downloaded. Can be a bitmap, string or byte array. </summary>
public object Data;
public DateTime TimeAdded, TimeDownloaded;
/// <summary> Instant in time the item was originally added to the download queue. </summary>
public DateTime TimeAdded;
/// <summary> Instant in time the item was fully downloaded. </summary>
public DateTime TimeDownloaded;
/// <summary>
///
/// </summary>
public string Url;
public DownloadedItem( object data, DateTime timeAdded, string url ) {

View file

@ -1,8 +1,6 @@
using System;
using System.Drawing;
using ClassicalSharp.GraphicsAPI;
using OpenTK;
using OpenTK;
namespace ClassicalSharp.Renderers {