diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj
index 124d08550..52c5cb0ce 100644
--- a/ClassicalSharp/ClassicalSharp.csproj
+++ b/ClassicalSharp/ClassicalSharp.csproj
@@ -35,7 +35,7 @@
DEBUG;TRACE;
Project
obj\
- wwwf mppass 127.0.0.1 25565
+ wwwf sdf 127.0.0.1 25565
..\output\release\
diff --git a/ClassicalSharp/Map/Map.cs b/ClassicalSharp/Map/Map.cs
index fe523c911..30c97b18d 100644
--- a/ClassicalSharp/Map/Map.cs
+++ b/ClassicalSharp/Map/Map.cs
@@ -279,7 +279,7 @@ namespace ClassicalSharp {
/// Unpacks the given index into the map's block array into its original world coordinates.
public Vector3I GetCoords( int index ) {
if( index < 0 || index >= mapData.Length )
- return new Vector3I( -1, -1, -1 );
+ return new Vector3I( -1 );
int x = index % Width;
int y = index / oneY; // index / (width * length)
int z = (index / Width) % Length;
diff --git a/ClassicalSharp/Network/NetworkProcessor.cs b/ClassicalSharp/Network/NetworkProcessor.cs
index 6ded88d4f..de6613754 100644
--- a/ClassicalSharp/Network/NetworkProcessor.cs
+++ b/ClassicalSharp/Network/NetworkProcessor.cs
@@ -148,6 +148,10 @@ namespace ClassicalSharp {
NetWriter writer;
void SendPacket() {
+ if( Disconnected ) {
+ writer.index = 0;
+ return;
+ }
try {
writer.Send( Disconnected );
} catch( IOException ex ) {
@@ -163,9 +167,9 @@ namespace ClassicalSharp {
void ReadPacket( byte opcode ) {
reader.Remove( 1 ); // remove opcode
lastOpcode = (PacketId)opcode;
- Action handler;
+ Action handler = handlers[opcode];
- if( opcode >= maxHandledPacket || (handler = handlers[opcode]) == null)
+ if( handler == null )
throw new NotImplementedException( "Unsupported packet:" + (PacketId)opcode );
handler();
}
diff --git a/ClassicalSharp/Network/Utils/NetWriter.cs b/ClassicalSharp/Network/Utils/NetWriter.cs
index 4639bbbcf..8b33d00fb 100644
--- a/ClassicalSharp/Network/Utils/NetWriter.cs
+++ b/ClassicalSharp/Network/Utils/NetWriter.cs
@@ -53,10 +53,8 @@ namespace ClassicalSharp {
}
public void Send( bool disconnected ) {
- int packetLength = index;
+ Stream.Write( buffer, 0, index );
index = 0;
- if( !disconnected )
- Stream.Write( buffer, 0, packetLength );
}
}
}
\ No newline at end of file
diff --git a/ClassicalSharp/Particles/CollidableParticle.cs b/ClassicalSharp/Particles/CollidableParticle.cs
index de9d4c143..49aa0e3fa 100644
--- a/ClassicalSharp/Particles/CollidableParticle.cs
+++ b/ClassicalSharp/Particles/CollidableParticle.cs
@@ -5,17 +5,22 @@ namespace ClassicalSharp.Particles {
public abstract class CollidableParticle : Particle {
- const float gravity = 3.4f;
- //const float gravity = 0.7f; // TODO: temp debug
+ protected bool hitTerrain = false;
+ public CollidableParticle( Game game ) : base( game) { }
- public CollidableParticle( Game game, Vector3 pos, Vector3 velocity, double lifetime )
- : base( game, pos, velocity, lifetime ) {
+ public void ResetState( Vector3 pos, Vector3 velocity, double lifetime ) {
+ Position = lastPos = nextPos = pos;
+ Velocity = velocity;
+ Lifetime = (float)lifetime;
+ hitTerrain = false;
}
- public override bool Tick( double delta ) {
+ protected bool Tick( float gravity, double delta ) {
+ hitTerrain = false;
lastPos = Position = nextPos;
byte curBlock = game.Map.SafeGetBlock( (int)Position.X, (int)Position.Y, (int)Position.Z );
- if( !CanPassThrough( curBlock ) ) return true;
+ float blockY = (int)Position.Y + game.BlockInfo.Height[curBlock];
+ if( !CanPassThrough( curBlock ) && Position.Y < blockY ) return true;
Velocity.Y -= gravity * (float)delta;
int startY = (int)Math.Floor( Position.Y );
@@ -25,34 +30,34 @@ namespace ClassicalSharp.Particles {
Utils.Clamp( ref Position.Z, 0, game.Map.Length - 0.01f );
if( Velocity.Y > 0 ) {
- for( int y = startY; y <= endY && TestY( y, false ); y++ );
+ // don't test block we are already in
+ for( int y = startY + 1; y <= endY && TestY( y, false ); y++ );
} else {
for( int y = startY; y >= endY && TestY( y, true ); y-- );
}
nextPos = Position;
Position = lastPos;
return base.Tick( delta );
- }
+ }
bool TestY( int y, bool topFace ) {
if( y < 0 ) {
Position.Y = nextPos.Y = lastPos.Y = 0 + Entity.Adjustment;
Velocity = Vector3.Zero;
+ hitTerrain = true;
return false;
}
byte block = game.Map.SafeGetBlock( (int)Position.X, y, (int)Position.Z );
if( CanPassThrough( block ) ) return true;
- float collideY = y;
- if( topFace )
- collideY += game.BlockInfo.Height[block];
-
- bool collide = topFace ? (Position.Y < collideY) : (Position.Y > collideY );
+ float collideY = y + (topFace ? game.BlockInfo.Height[block] : 0);
+ bool collide = topFace ? (Position.Y < collideY) : (Position.Y > collideY);
if( collide ) {
float adjust = topFace ? Entity.Adjustment : -Entity.Adjustment;
Position.Y = nextPos.Y = lastPos.Y = collideY + adjust;
Velocity = Vector3.Zero;
+ hitTerrain = true;
return false;
}
return true;
diff --git a/ClassicalSharp/Particles/Particle.cs b/ClassicalSharp/Particles/Particle.cs
index 6ff57d9f9..d47021963 100644
--- a/ClassicalSharp/Particles/Particle.cs
+++ b/ClassicalSharp/Particles/Particle.cs
@@ -13,12 +13,7 @@ namespace ClassicalSharp.Particles {
public abstract void Render( double delta, float t, VertexPos3fTex2fCol4b[] vertices, ref int index );
- public Particle( Game game, Vector3 pos, Vector3 velocity, double lifetime ) {
- this.game = game;
- Position = lastPos = nextPos = pos;
- Velocity = velocity;
- Lifetime = (float)lifetime;
- }
+ public Particle( Game game ) { this.game = game; }
public virtual bool Tick( double delta ) {
Lifetime -= (float)delta;
diff --git a/ClassicalSharp/Particles/ParticleManager.cs b/ClassicalSharp/Particles/ParticleManager.cs
index 115206830..326c3c1a0 100644
--- a/ClassicalSharp/Particles/ParticleManager.cs
+++ b/ClassicalSharp/Particles/ParticleManager.cs
@@ -8,32 +8,35 @@ namespace ClassicalSharp.Particles {
public class ParticleManager : IDisposable {
public int ParticlesTexId;
- List terrainParticles = new List();
- List rainParticles = new List();
+ TerrainParticle[] terrainParticles = new TerrainParticle[maxParticles];
+ RainParticle[] rainParticles = new RainParticle[maxParticles];
+ int terrainCount, rainCount;
+
Game game;
Random rnd;
int vb;
+ const int maxParticles = 600;
public ParticleManager( Game game ) {
this.game = game;
rnd = new Random();
- vb = game.Graphics.CreateDynamicVb( VertexFormat.Pos3fTex2fCol4b, 1000 );
+ vb = game.Graphics.CreateDynamicVb( VertexFormat.Pos3fTex2fCol4b, maxParticles * 4 );
}
VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[0];
public void Render( double delta, float t ) {
- if( terrainParticles.Count == 0 && rainParticles.Count == 0 ) return;
+ if( terrainCount == 0 && rainCount == 0 ) return;
IGraphicsApi graphics = game.Graphics;
graphics.Texturing = true;
graphics.AlphaTest = true;
graphics.SetBatchFormat( VertexFormat.Pos3fTex2fCol4b );
- int count = RenderParticles( terrainParticles, delta, t );
+ int count = RenderParticles( terrainParticles, terrainCount, delta, t );
if( count > 0 ) {
graphics.BindTexture( game.TerrainAtlas.TexId );
graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, vb, vertices, count, count * 6 / 4 );
}
- count = RenderParticles( rainParticles, delta, t );
+ count = RenderParticles( rainParticles, rainCount, delta, t );
if( count > 0 ) {
graphics.BindTexture( ParticlesTexId );
graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, vb, vertices, count, count * 6 / 4 );
@@ -43,27 +46,27 @@ namespace ClassicalSharp.Particles {
graphics.Texturing = false;
}
- int RenderParticles( List particles, double delta, float t ) {
- int count = particles.Count * 4;
+ int RenderParticles( Particle[] particles, int elems, double delta, float t ) {
+ int count = elems * 4;
if( count > vertices.Length )
vertices = new VertexPos3fTex2fCol4b[count];
int index = 0;
- for( int i = 0; i < particles.Count; i++ )
- particles[i].Render( delta, t, vertices, ref index );
- return Math.Min( count, 1000 );
+ for( int i = 0; i < elems; i++ )
+ particles[i].Render( delta, t, vertices, ref index );
+ return Math.Min( count, maxParticles * 4 );
}
public void Tick( double delta ) {
- TickParticles( terrainParticles, delta );
- TickParticles( rainParticles, delta );
+ TickParticles( terrainParticles, ref terrainCount, delta );
+ TickParticles( rainParticles, ref rainCount, delta );
}
- void TickParticles( List particles, double delta ) {
- for( int i = 0; i < particles.Count; i++ ) {
+ void TickParticles( Particle[] particles, ref int count, double delta ) {
+ for( int i = 0; i < count; i++ ) {
Particle particle = particles[i];
if( particle.Tick( delta ) ) {
- particles.RemoveAt( i );
+ RemoveAt( i, particles, ref count );
i--;
}
}
@@ -103,27 +106,56 @@ namespace ClassicalSharp.Particles {
particleRec.V2 = particleRec.V1 + elemSize;
double life = 1.5 - rnd.NextDouble();
- terrainParticles.Add( new TerrainParticle( game, pos, velocity, life, particleRec ) );
+ TerrainParticle p = AddParticle( terrainParticles, ref terrainCount, false );
+ p.ResetState( pos, velocity, life );
+ p.rec = particleRec;
}
}
public void AddRainParticle( Vector3 pos ) {
- Vector3 startPos = pos;
-
- for( int i = 0; i < 5; i++ ) {
+ Vector3 startPos = pos;
+ for( int i = 0; i < 2; i++ ) {
double velX = rnd.NextDouble() * 0.8 - 0.4; // [-0.4, 0.4]
double velZ = rnd.NextDouble() * 0.8 - 0.4;
- double velY = rnd.NextDouble() + 0.5;
+ double velY = rnd.NextDouble() + 0.4;
Vector3 velocity = new Vector3( (float)velX, (float)velY, (float)velZ );
double xOffset = rnd.NextDouble() - 0.5; // [-0.5, 0.5]
- double yOffset = 0.01;
+ double yOffset = rnd.NextDouble() * 0.1 + 0.01;
double zOffset = rnd.NextDouble() - 0.5;
pos = startPos + new Vector3( 0.5f + (float)xOffset,
(float)yOffset, 0.5f + (float)zOffset );
- double life = 3.5 - rnd.NextDouble();
- rainParticles.Add( new RainParticle( game, pos, velocity, life ) );
+ double life = 40;
+ RainParticle p = AddParticle( rainParticles, ref rainCount, true );
+ p.ResetState( pos, velocity, life );
+ p.Big = rnd.Next( 0, 20 ) >= 18;
+ p.Tiny = rnd.Next( 0, 30 ) >= 28;
}
}
+
+ T AddParticle( T[] particles, ref int count, bool rain ) where T : Particle {
+ if( count == maxParticles )
+ RemoveAt( 0, particles, ref count );
+ count++;
+
+ T old = particles[count - 1];
+ if( old != null ) return old;
+
+ T newT = rain ? (T)(object)new RainParticle( game )
+ : (T)(object)new TerrainParticle( game );
+ particles[count - 1] = newT;
+ return newT;
+ }
+
+ void RemoveAt( int index, T[] particles, ref int count ) where T : Particle {
+ T removed = particles[index];
+ for( int i = index; i < count - 1; i++ ) {
+ particles[i] = particles[i + 1];
+ }
+
+ particles[count - 1] = removed;
+ count--;
+ }
+
}
}
diff --git a/ClassicalSharp/Particles/RainParticle.cs b/ClassicalSharp/Particles/RainParticle.cs
index 32bc11e9e..cb5940bdc 100644
--- a/ClassicalSharp/Particles/RainParticle.cs
+++ b/ClassicalSharp/Particles/RainParticle.cs
@@ -5,16 +5,25 @@ namespace ClassicalSharp.Particles {
public sealed class RainParticle : CollidableParticle {
- static Vector2 rainSize = new Vector2( 1/8f, 1/8f );
+ static Vector2 bigSize = new Vector2( 1/16f, 1/16f );
+ static Vector2 smallSize = new Vector2( 0.75f/16f, 0.75f/16f );
+ static Vector2 tinySize = new Vector2( 0.5f/16f, 0.5f/16f );
static TextureRec rec = new TextureRec( 2/128f, 14/128f, 3/128f, 2/128f );
- public RainParticle( Game game, Vector3 pos, Vector3 velocity, double lifetime )
- : base( game, pos, velocity, lifetime ) {
+
+ public RainParticle( Game game ) : base( game ) { }
+
+ public bool Big, Tiny;
+
+ public override bool Tick( double delta ) {
+ bool dies = Tick( 3.5f, delta );
+ return hitTerrain ? true : dies;
}
public override void Render( double delta, float t, VertexPos3fTex2fCol4b[] vertices, ref int index ) {
Position = Vector3.Lerp( lastPos, nextPos, t );
Vector3 p111, p121, p212, p222;
- Utils.CalcBillboardPoints( rainSize, Position, ref game.View,
+ Vector2 size = Big ? bigSize : (Tiny ? tinySize : smallSize );
+ Utils.CalcBillboardPoints( size, Position, ref game.View,
out p111, out p121, out p212, out p222 );
Map map = game.Map;
FastColour col = map.IsLit( Vector3I.Floor( Position ) ) ? map.Sunlight : map.Shadowlight;
diff --git a/ClassicalSharp/Particles/TerrainParticle.cs b/ClassicalSharp/Particles/TerrainParticle.cs
index eabe5020b..08269995c 100644
--- a/ClassicalSharp/Particles/TerrainParticle.cs
+++ b/ClassicalSharp/Particles/TerrainParticle.cs
@@ -6,10 +6,12 @@ namespace ClassicalSharp.Particles {
public sealed class TerrainParticle : CollidableParticle {
static Vector2 terrainSize = new Vector2( 1/8f, 1/8f );
- TextureRec rec;
- public TerrainParticle( Game game, Vector3 pos, Vector3 velocity, double lifetime, TextureRec rec )
- : base( game, pos, velocity, lifetime ) {
- this.rec = rec;
+ internal TextureRec rec;
+
+ public TerrainParticle( Game game ) : base( game ) { }
+
+ public override bool Tick( double delta ) {
+ return Tick( 5.4f, delta );
}
public override void Render( double delta, float t, VertexPos3fTex2fCol4b[] vertices, ref int index ) {
diff --git a/ClassicalSharp/Rendering/WeatherRenderer.cs b/ClassicalSharp/Rendering/WeatherRenderer.cs
index 7e0ca2916..d59803af8 100644
--- a/ClassicalSharp/Rendering/WeatherRenderer.cs
+++ b/ClassicalSharp/Rendering/WeatherRenderer.cs
@@ -24,6 +24,7 @@ namespace ClassicalSharp {
const int extent = 4;
VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[8 * (extent * 2 + 1) * (extent * 2 + 1)];
double rainAcc;
+ Vector3I lastPos = new Vector3I( Int32.MinValue );
public void Render( double deltaTime ) {
Weather weather = map.Weather;
@@ -33,12 +34,14 @@ namespace ClassicalSharp {
graphics.BindTexture( weather == Weather.Rainy ? game.RainTexId : game.SnowTexId );
Vector3 eyePos = game.LocalPlayer.EyePosition;
Vector3 camPos = game.Camera.GetCameraPos( eyePos );
- Vector3I pos = Vector3I.Floor( eyePos ); // TODO: cam pos
+ Vector3I pos = Vector3I.Floor( camPos );
+ bool moved = pos != lastPos;
+ lastPos = pos;
float speed = weather == Weather.Rainy ? 1f : 0.25f;
vOffset = -(float)game.accumulator * speed;
rainAcc += deltaTime;
-
+
int index = 0;
graphics.AlphaBlending = true;
graphics.DepthWrite = false;
@@ -49,16 +52,15 @@ namespace ClassicalSharp {
float height = Math.Max( game.Map.Height, pos.Y + 64 ) - rainY;
if( height <= 0 ) continue;
- //if( rainAcc >= 2 )
- // game.ParticleManager.AddRainParticle( new Vector3( pos.X + dx, rainY, pos.Z + dz ) );
+ if( rainAcc >= 0.25 || moved )
+ game.ParticleManager.AddRainParticle( new Vector3( pos.X + dx, rainY, pos.Z + dz ) );
col.A = (byte)Math.Max( 0, AlphaAt( dx * dx + dz * dz ) );
MakeRainForSquare( pos.X + dx, rainY, height, pos.Z + dz, col, ref index );
}
}
- if( rainAcc >= 2 )
+ if( rainAcc >= 0.25 || moved )
rainAcc = 0;
- // fixes crashing on nVidia cards in OpenGL builds.
if( index > 0 ) {
graphics.SetBatchFormat( VertexFormat.Pos3fTex2fCol4b );
graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, weatherVb, vertices, index, index * 6 / 4 );
@@ -92,6 +94,7 @@ namespace ClassicalSharp {
int length, width, maxY, oneY;
void OnNewMap( object sender, EventArgs e ) {
heightmap = null;
+ lastPos = new Vector3I( Int32.MaxValue );
}
void OnNewMapLoaded( object sender, EventArgs e ) {
diff --git a/ClassicalSharp/Singleplayer/Server.cs b/ClassicalSharp/Singleplayer/Server.cs
index 859e87460..b5d39196e 100644
--- a/ClassicalSharp/Singleplayer/Server.cs
+++ b/ClassicalSharp/Singleplayer/Server.cs
@@ -104,7 +104,7 @@ namespace ClassicalSharp.Singleplayer {
this.generator = generator;
game.SetNewScreen( new LoadingMapScreen( game, "Single player", "Generating.." ) );
- generator.GenerateAsync( game, width, height, length, 0 );
+ generator.GenerateAsync( game, width, height, length, seed );
}
unsafe void MapSet( int width, int length, byte* ptr, int yStart, int yEnd, byte block ) {
diff --git a/ClassicalSharp/Utils/Vector3I.cs b/ClassicalSharp/Utils/Vector3I.cs
index 3b0300134..604c86ca2 100644
--- a/ClassicalSharp/Utils/Vector3I.cs
+++ b/ClassicalSharp/Utils/Vector3I.cs
@@ -28,15 +28,11 @@ namespace ClassicalSharp {
}
public Vector3I( int x, int y, int z ) {
- X = x;
- Y = y;
- Z = z;
+ X = x; Y = y; Z = z;
}
public Vector3I( int value ) {
- X = value;
- Y = value;
- Z = value;
+ X = value; Y = value; Z = value;
}
public static Vector3I operator + ( Vector3I left, Vector3I right ) {