mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 11:06:06 -04:00
Client should provide visual feedback when respawning/spawning by slightly teleporting the player up one pixel. (Thanks FrostFox) Closes #158
This commit is contained in:
parent
4946926552
commit
fb0fdce7ab
@ -150,6 +150,7 @@
|
|||||||
<Compile Include="Entities\AI\HostileAI.cs" />
|
<Compile Include="Entities\AI\HostileAI.cs" />
|
||||||
<Compile Include="Entities\Components\AnimatedComponent.cs" />
|
<Compile Include="Entities\Components\AnimatedComponent.cs" />
|
||||||
<Compile Include="Entities\Components\HacksComponent.cs" />
|
<Compile Include="Entities\Components\HacksComponent.cs" />
|
||||||
|
<Compile Include="Entities\Components\InputComponent.cs" />
|
||||||
<Compile Include="Entities\Components\InterpolatedComponent.cs" />
|
<Compile Include="Entities\Components\InterpolatedComponent.cs" />
|
||||||
<Compile Include="Entities\Components\CollisionsComponent.cs" />
|
<Compile Include="Entities\Components\CollisionsComponent.cs" />
|
||||||
<Compile Include="Entities\Components\PhysicsComponent.cs" />
|
<Compile Include="Entities\Components\PhysicsComponent.cs" />
|
||||||
|
94
ClassicalSharp/Entities/Components/InputComponent.cs
Normal file
94
ClassicalSharp/Entities/Components/InputComponent.cs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||||
|
using System;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Input;
|
||||||
|
|
||||||
|
namespace ClassicalSharp.Entities {
|
||||||
|
|
||||||
|
/// <summary> Entity component that performs input handling. </summary>
|
||||||
|
public sealed class InputComponent {
|
||||||
|
|
||||||
|
Entity entity;
|
||||||
|
Game game;
|
||||||
|
public HacksComponent Hacks;
|
||||||
|
public CollisionsComponent collisions;
|
||||||
|
public PhysicsComponent physics;
|
||||||
|
|
||||||
|
public InputComponent( Game game, Entity entity ) {
|
||||||
|
this.game = game;
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool HandleKeyDown( Key key ) {
|
||||||
|
LocalPlayer p = (LocalPlayer)entity;
|
||||||
|
KeyMap keys = game.InputHandler.Keys;
|
||||||
|
|
||||||
|
if( key == keys[KeyBinding.Respawn] && Hacks.CanRespawn ) {
|
||||||
|
Vector3 spawn = p.SpawnPoint;
|
||||||
|
if( game.World.IsValidPos( Vector3I.Floor( spawn ) ) )
|
||||||
|
FindHighestFree( ref spawn );
|
||||||
|
|
||||||
|
spawn.Y += 1/16f;
|
||||||
|
LocationUpdate update = LocationUpdate.MakePosAndOri( spawn, p.SpawnYaw, p.SpawnPitch, false );
|
||||||
|
entity.SetLocation( update, false );
|
||||||
|
} else if( key == keys[KeyBinding.SetSpawn] && Hacks.CanRespawn ) {
|
||||||
|
p.SpawnPoint = entity.Position;
|
||||||
|
p.SpawnYaw = entity.YawDegrees;
|
||||||
|
p.SpawnPitch = entity.PitchDegrees;
|
||||||
|
|
||||||
|
Vector3 spawn = p.SpawnPoint; spawn.Y += 1/16f;
|
||||||
|
LocationUpdate update = LocationUpdate.MakePosAndOri( spawn, p.SpawnYaw, p.SpawnPitch, false );
|
||||||
|
entity.SetLocation( update, false );
|
||||||
|
} else if( key == keys[KeyBinding.Fly] && Hacks.CanFly && Hacks.Enabled ) {
|
||||||
|
Hacks.Flying = !Hacks.Flying;
|
||||||
|
} else if( key == keys[KeyBinding.NoClip] && Hacks.CanNoclip && Hacks.Enabled ) {
|
||||||
|
if( Hacks.Noclip ) entity.Velocity.Y = 0;
|
||||||
|
Hacks.Noclip = !Hacks.Noclip;
|
||||||
|
} else if( key == keys[KeyBinding.Jump] && !entity.onGround && !(Hacks.Flying || Hacks.Noclip) ) {
|
||||||
|
if( !physics.firstJump && Hacks.CanDoubleJump && Hacks.DoubleJump ) {
|
||||||
|
physics.DoNormalJump();
|
||||||
|
physics.firstJump = true;
|
||||||
|
} else if( !physics.secondJump && Hacks.CanDoubleJump && Hacks.DoubleJump ) {
|
||||||
|
physics.DoNormalJump();
|
||||||
|
physics.secondJump = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindHighestFree( ref Vector3 spawn ) {
|
||||||
|
BlockInfo info = game.BlockInfo;
|
||||||
|
Vector3 size = entity.Model.CollisionSize;
|
||||||
|
BoundingBox bb = entity.CollisionBounds;
|
||||||
|
Vector3I P = Vector3I.Floor( spawn );
|
||||||
|
int bbMax = Utils.Floor( size.Y );
|
||||||
|
int minX = Utils.Floor( -size.X / 2 ), maxX = Utils.Floor( size.X / 2 );
|
||||||
|
int minZ = Utils.Floor( -size.Z / 2 ), maxZ = Utils.Floor( size.Z / 2 );
|
||||||
|
|
||||||
|
// Spawn player at highest valid position.
|
||||||
|
for( int y = P.Y; y <= game.World.Height; y++ ) {
|
||||||
|
bool anyHit = false;
|
||||||
|
for( int yy = 0; yy <= bbMax; yy++ )
|
||||||
|
for( int zz = minZ; zz <= maxZ; zz++ )
|
||||||
|
for ( int xx = minX; xx <= maxX; xx++ )
|
||||||
|
{
|
||||||
|
Vector3I coords = new Vector3I( P.X + xx, y + yy, P.Z + zz );
|
||||||
|
byte block = collisions.GetPhysicsBlockId( coords.X, coords.Y, coords.Z );
|
||||||
|
Vector3 min = info.MinBB[block] + (Vector3)coords;
|
||||||
|
Vector3 max = info.MaxBB[block] + (Vector3)coords;
|
||||||
|
if( !bb.Intersects( new BoundingBox( min, max ) ) ) continue;
|
||||||
|
anyHit |= info.Collide[block] == CollideType.Solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !anyHit ) {
|
||||||
|
byte block = collisions.GetPhysicsBlockId( P.X, y, P.Z );
|
||||||
|
float height = info.Collide[block] == CollideType.Solid ? info.MaxBB[block].Y : 0;
|
||||||
|
spawn.Y = y + height + Entity.Adjustment;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,7 @@ namespace ClassicalSharp.Entities {
|
|||||||
internal CollisionsComponent collisions;
|
internal CollisionsComponent collisions;
|
||||||
public HacksComponent Hacks;
|
public HacksComponent Hacks;
|
||||||
internal PhysicsComponent physics;
|
internal PhysicsComponent physics;
|
||||||
|
internal InputComponent input;
|
||||||
|
|
||||||
public LocalPlayer( Game game ) : base( game ) {
|
public LocalPlayer( Game game ) : base( game ) {
|
||||||
DisplayName = game.Username;
|
DisplayName = game.Username;
|
||||||
@ -36,8 +37,10 @@ namespace ClassicalSharp.Entities {
|
|||||||
collisions = new CollisionsComponent( game, this );
|
collisions = new CollisionsComponent( game, this );
|
||||||
Hacks = new HacksComponent( game, this );
|
Hacks = new HacksComponent( game, this );
|
||||||
physics = new PhysicsComponent( game, this );
|
physics = new PhysicsComponent( game, this );
|
||||||
physics.hacks = Hacks;
|
input = new InputComponent( game, this );
|
||||||
physics.collisions = collisions;
|
physics.hacks = Hacks; input.Hacks = Hacks;
|
||||||
|
physics.collisions = collisions; input.collisions = collisions;
|
||||||
|
input.physics = physics;
|
||||||
|
|
||||||
Hacks.SpeedMultiplier = Options.GetFloat( OptionsKey.Speed, 0.1f, 50, 10 );
|
Hacks.SpeedMultiplier = Options.GetFloat( OptionsKey.Speed, 0.1f, 50, 10 );
|
||||||
Hacks.PushbackPlacing = !game.ClassicMode && Options.GetBool( OptionsKey.PushbackPlacing, false );
|
Hacks.PushbackPlacing = !game.ClassicMode && Options.GetBool( OptionsKey.PushbackPlacing, false );
|
||||||
@ -229,66 +232,6 @@ namespace ClassicalSharp.Entities {
|
|||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool HandleKeyDown( Key key ) {
|
internal bool HandleKeyDown( Key key ) { return input.HandleKeyDown( key ); }
|
||||||
KeyMap keys = game.InputHandler.Keys;
|
|
||||||
if( key == keys[KeyBinding.Respawn] && Hacks.CanRespawn ) {
|
|
||||||
Vector3 spawn = SpawnPoint;
|
|
||||||
if( game.World.IsValidPos( Vector3I.Floor( spawn ) ) )
|
|
||||||
FindHighestFree( ref spawn );
|
|
||||||
LocationUpdate update = LocationUpdate.MakePosAndOri( spawn, SpawnYaw, SpawnPitch, false );
|
|
||||||
SetLocation( update, false );
|
|
||||||
} else if( key == keys[KeyBinding.SetSpawn] && Hacks.CanRespawn ) {
|
|
||||||
SpawnPoint = Position;
|
|
||||||
SpawnYaw = HeadYawDegrees;
|
|
||||||
SpawnPitch = PitchDegrees;
|
|
||||||
} else if( key == keys[KeyBinding.Fly] && Hacks.CanFly && Hacks.Enabled ) {
|
|
||||||
Hacks.Flying = !Hacks.Flying;
|
|
||||||
} else if( key == keys[KeyBinding.NoClip] && Hacks.CanNoclip && Hacks.Enabled ) {
|
|
||||||
if( Hacks.Noclip ) Velocity.Y = 0;
|
|
||||||
Hacks.Noclip = !Hacks.Noclip;
|
|
||||||
} else if( key == keys[KeyBinding.Jump] && !onGround && !(Hacks.Flying || Hacks.Noclip) ) {
|
|
||||||
if( !physics.firstJump && Hacks.CanDoubleJump && Hacks.DoubleJump ) {
|
|
||||||
physics.DoNormalJump();
|
|
||||||
physics.firstJump = true;
|
|
||||||
} else if( !physics.secondJump && Hacks.CanDoubleJump && Hacks.DoubleJump ) {
|
|
||||||
physics.DoNormalJump();
|
|
||||||
physics.secondJump = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FindHighestFree( ref Vector3 spawn ) {
|
|
||||||
Vector3 size = Model.CollisionSize;
|
|
||||||
BoundingBox bb = CollisionBounds;
|
|
||||||
Vector3I P = Vector3I.Floor( spawn );
|
|
||||||
int bbMax = Utils.Floor( size.Y );
|
|
||||||
int minX = Utils.Floor( -size.X / 2 ), maxX = Utils.Floor( size.X / 2 );
|
|
||||||
int minZ = Utils.Floor( -size.Z / 2 ), maxZ = Utils.Floor( size.Z / 2 );
|
|
||||||
|
|
||||||
// Spawn player at highest valid position.
|
|
||||||
for( int y = P.Y; y <= game.World.Height; y++ ) {
|
|
||||||
bool anyHit = false;
|
|
||||||
for( int yy = 0; yy <= bbMax; yy++ )
|
|
||||||
for( int zz = minZ; zz <= maxZ; zz++ )
|
|
||||||
for ( int xx = minX; xx <= maxX; xx++ )
|
|
||||||
{
|
|
||||||
Vector3I coords = new Vector3I( P.X + xx, y + yy, P.Z + zz );
|
|
||||||
byte block = collisions.GetPhysicsBlockId( coords.X, coords.Y, coords.Z );
|
|
||||||
Vector3 min = info.MinBB[block] + (Vector3)coords;
|
|
||||||
Vector3 max = info.MaxBB[block] + (Vector3)coords;
|
|
||||||
if( !bb.Intersects( new BoundingBox( min, max ) ) ) continue;
|
|
||||||
anyHit |= info.Collide[block] == CollideType.Solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !anyHit ) {
|
|
||||||
byte block = collisions.GetPhysicsBlockId( P.X, y, P.Z );
|
|
||||||
spawn.Y = y + info.MaxBB[block].Y + Entity.Adjustment;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user