Revert "Remove /client commands (pointless when you can just do /client), have all commands enabled in both multiplayer and singleplayer modes. (But singleplayer only commands will show 'disabled' in multiplayer)"

This reverts commit 1e46e4ad96c3399fc4fb857d60613826f7cc06eb.
This commit is contained in:
UnknownShadow200 2017-11-25 18:30:41 +11:00
parent 1e46e4ad96
commit bd04b98508
8 changed files with 200 additions and 205 deletions

View File

@ -146,7 +146,7 @@
<Compile Include="Blocks\BlockInfo.Culling.cs" />
<Compile Include="Blocks\BlockInfo.Atlas.cs" />
<Compile Include="Blocks\DefaultSet.cs" />
<Compile Include="Commands\Commands.cs" />
<Compile Include="Commands\SinglePlayerCommands.cs" />
<Compile Include="Entities\Components\IInterpComponent.cs" />
<Compile Include="Entities\Mobs\AI.cs" />
<Compile Include="Entities\Components\AnimatedComponent.cs" />
@ -222,6 +222,8 @@
<Compile Include="GraphicsAPI\Direct3D9Api.cs" />
<Compile Include="GraphicsAPI\IGraphicsApi.cs" />
<Compile Include="GraphicsAPI\OpenGLApi.cs" />
<Compile Include="Commands\Command.cs" />
<Compile Include="Commands\DefaultCommands.cs" />
<Compile Include="GraphicsAPI\VertexFormats.cs" />
<Compile Include="Hotkeys\HotkeyList.cs" />
<Compile Include="Hotkeys\LwjglToKey.cs" />

View File

@ -0,0 +1,21 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
namespace ClassicalSharp.Commands {
/// <summary> Represents a client side action that optionally accepts arguments. </summary>
public abstract class Command {
/// <summary> Full command name, note that the user does not
/// have to fully type this into chat. </summary>
public string Name;
/// <summary> Provides help about the purpose and syntax of this
/// command. Can use colour codes. </summary>
public string[] Help;
protected internal Game game;
public abstract void Execute(string[] args);
}
}

View File

@ -4,16 +4,6 @@ using System.Collections.Generic;
namespace ClassicalSharp.Commands {
/// <summary> Represents a client side action that optionally accepts arguments. </summary>
public abstract class Command {
public string Name;
public string[] Help;
public bool SingleplayerOnly;
protected internal Game game;
public abstract void Execute(string[] args);
}
public class CommandList : IGameComponent {
const string prefix = "/client";
@ -29,10 +19,13 @@ namespace ClassicalSharp.Commands {
public List<Command> RegisteredCommands = new List<Command>();
public void Init(Game game) {
this.game = game;
Register(new CommandsCommand());
Register(new GpuInfoCommand());
Register(new HelpCommand());
Register(new RenderTypeCommand());
Register(new ResolutionCommand());
if (!game.Server.IsSinglePlayer) return;
Register(new ModelCommand());
Register(new CuboidCommand());
Register(new TeleportCommand());
@ -45,6 +38,11 @@ namespace ClassicalSharp.Commands {
public void Register(Command command) {
command.game = game;
for (int i = 0; i < RegisteredCommands.Count; i++) {
Command cmd = RegisteredCommands[i];
if (Utils.CaselessEquals(cmd.Name, command.Name))
throw new InvalidOperationException("Another command already has name : " + command.Name);
}
RegisteredCommands.Add(command);
}
@ -61,15 +59,8 @@ namespace ClassicalSharp.Commands {
match = cmd;
}
if (match == null) {
if (match == null)
game.Chat.Add("&e/client: Unrecognised command: \"&f" + cmdName + "&e\".");
game.Chat.Add("&e/client: Type &a/client &efor a list of commands.");
return null;
}
if (match.SingleplayerOnly && !game.Server.IsSinglePlayer) {
game.Chat.Add("&e/client: \"&f" + cmdName + "&e\" can only be used in singleplayer.");
return null;
}
return match;
}
@ -84,7 +75,7 @@ namespace ClassicalSharp.Commands {
if (text.Length == 0) { // only / or /client
game.Chat.Add("&eList of client commands:");
PrintDefinedCommands(game);
game.Chat.Add("&eTo see a particular command's help, type &a/client help [cmd name]");
game.Chat.Add("&eTo see a particular command's help, type /client help [cmd name]");
return;
}

View File

@ -0,0 +1,120 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using ClassicalSharp.Renderers;
using OpenTK.Input;
namespace ClassicalSharp.Commands {
/// <summary> Command that displays the list of all currently registered client commands. </summary>
public sealed class CommandsCommand : Command {
public CommandsCommand() {
Name = "Commands";
Help = new string[] {
"&a/client commands",
"&ePrints a list of all usable commands"
};
}
public override void Execute(string[] args) {
game.CommandList.PrintDefinedCommands(game);
}
}
/// <summary> Command that displays information about an input client command. </summary>
public sealed class HelpCommand : Command {
public HelpCommand() {
Name = "Help";
Help = new string[] {
"&a/client help [command name]",
"&eDisplays the help for the given command.",
};
}
public override void Execute(string[] args) {
if (args.Length == 1) {
game.Chat.Add("&eList of client commands:");
game.CommandList.PrintDefinedCommands(game);
game.Chat.Add("&eTo see a particular command's help, type /client help [cmd name]");
} else {
Command cmd = game.CommandList.GetMatch(args[1]);
if (cmd == null) return;
string[] help = cmd.Help;
for (int i = 0; i < help.Length; i++)
game.Chat.Add(help[i]);
}
}
}
/// <summary> Command that displays information about the user's GPU. </summary>
public sealed class GpuInfoCommand : Command {
public GpuInfoCommand() {
Name = "GpuInfo";
Help = new string[] {
"&a/client gpuinfo",
"&eDisplays information about your GPU.",
};
}
public override void Execute(string[] args) {
string[] lines = game.Graphics.ApiInfo;
for (int i = 0; i < lines.Length; i++)
game.Chat.Add("&a" + lines[i]);
}
}
public sealed class RenderTypeCommand : Command {
public RenderTypeCommand() {
Name = "RenderType";
Help = new string[] {
"&a/client rendertype [normal/legacy/legacyfast]",
"&bnormal: &eDefault renderer, with all environmental effects enabled.",
"&blegacy: &eMay be slightly slower than normal, but produces the same environmental effects.",
"&blegacyfast: &eSacrifices clouds, fog and overhead sky for faster performance.",
"&bnormalfast: &eSacrifices clouds, fog and overhead sky for faster performance.",
};
}
public override void Execute(string[] args) {
if (args.Length == 1) {
game.Chat.Add("&e/client: &cYou didn't specify a new render type.");
} else if (game.SetRenderType(args[1])) {
game.Chat.Add("&e/client: &fRender type is now " + args[1] + ".");
} else {
game.Chat.Add("&e/client: &cUnrecognised render type &f\"" + args[1] + "\"&c.");
}
}
}
public sealed class ResolutionCommand : Command {
public ResolutionCommand() {
Name = "Resolution";
Help = new string[] {
"&a/client resolution [width] [height]",
"&ePrecisely sets the size of the rendered window.",
};
}
public override void Execute(string[] args) {
int width, height;
if (args.Length < 3) {
game.Chat.Add("&e/client: &cYou didn't specify width and height");
} else if (!Int32.TryParse(args[1], out width) || !Int32.TryParse(args[2], out height)) {
game.Chat.Add("&e/client: &cWidth and height must be integers.");
} else if (width <= 0 || height <= 0) {
game.Chat.Add("&e/client: &cWidth and height must be above 0.");
} else {
game.window.ClientSize = new Size(width, height);
Options.Set(OptionsKey.WindowWidth, width);
Options.Set(OptionsKey.WindowHeight, height);
}
}
}
}

View File

@ -1,13 +1,13 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using ClassicalSharp.Entities;
using ClassicalSharp.Events;
using ClassicalSharp.Renderers;
using OpenTK;
using OpenTK.Input;
using OpenTK;
#if USE16_BIT
using BlockID = System.UInt16;
#else
@ -16,99 +16,6 @@ using BlockID = System.Byte;
namespace ClassicalSharp.Commands {
public sealed class HelpCommand : Command {
public HelpCommand() {
Name = "Help";
Help = new string[] {
"&a/client help [command name]",
"&eDisplays the help for the given command.",
};
}
public override void Execute(string[] args) {
if (args.Length == 1) {
game.Chat.Add("&eList of client commands:");
game.CommandList.PrintDefinedCommands(game);
game.Chat.Add("&eTo see a particular command's help, type /client help [cmd name]");
} else {
Command cmd = game.CommandList.GetMatch(args[1]);
if (cmd == null) return;
string[] help = cmd.Help;
for (int i = 0; i < help.Length; i++)
game.Chat.Add(help[i]);
}
}
}
public sealed class GpuInfoCommand : Command {
public GpuInfoCommand() {
Name = "GpuInfo";
Help = new string[] {
"&a/client gpuinfo",
"&eDisplays information about your GPU.",
};
}
public override void Execute(string[] args) {
string[] lines = game.Graphics.ApiInfo;
for (int i = 0; i < lines.Length; i++)
game.Chat.Add("&a" + lines[i]);
}
}
public sealed class RenderTypeCommand : Command {
public RenderTypeCommand() {
Name = "RenderType";
Help = new string[] {
"&a/client rendertype [normal/legacy/legacyfast]",
"&bnormal: &eDefault renderer, with all environmental effects enabled.",
"&blegacy: &eMay be slightly slower than normal, but produces the same environmental effects.",
"&blegacyfast: &eSacrifices clouds, fog and overhead sky for faster performance.",
"&bnormalfast: &eSacrifices clouds, fog and overhead sky for faster performance.",
};
}
public override void Execute(string[] args) {
if (args.Length == 1) {
game.Chat.Add("&e/client: &cYou didn't specify a new render type.");
} else if (game.SetRenderType(args[1])) {
game.Chat.Add("&e/client: &fRender type is now " + args[1] + ".");
} else {
game.Chat.Add("&e/client: &cUnrecognised render type &f\"" + args[1] + "\"&c.");
}
}
}
public sealed class ResolutionCommand : Command {
public ResolutionCommand() {
Name = "Resolution";
Help = new string[] {
"&a/client resolution [width] [height]",
"&ePrecisely sets the size of the rendered window.",
};
}
public override void Execute(string[] args) {
int width, height;
if (args.Length < 3) {
game.Chat.Add("&e/client: &cYou didn't specify width and height");
} else if (!Int32.TryParse(args[1], out width) || !Int32.TryParse(args[2], out height)) {
game.Chat.Add("&e/client: &cWidth and height must be integers.");
} else if (width <= 0 || height <= 0) {
game.Chat.Add("&e/client: &cWidth and height must be above 0.");
} else {
game.window.ClientSize = new Size(width, height);
Options.Set(OptionsKey.WindowWidth, width);
Options.Set(OptionsKey.WindowHeight, height);
}
}
}
public sealed class ModelCommand : Command {
public ModelCommand() {
@ -118,7 +25,6 @@ namespace ClassicalSharp.Commands {
"&bnames: &echibi, chicken, creeper, human, pig, sheep",
"&e skeleton, spider, zombie, sitting, <numerical block id>",
};
SingleplayerOnly = true;
}
public override void Execute(string[] args) {
@ -141,7 +47,6 @@ namespace ClassicalSharp.Commands {
"&e If persist is given and is \"yes\", then the command",
"&e will repeatedly cuboid, without needing to be typed in again.",
};
SingleplayerOnly = true;
}
int block = -1;
Vector3I mark1, mark2;
@ -221,12 +126,11 @@ namespace ClassicalSharp.Commands {
public sealed class TeleportCommand : Command {
public TeleportCommand() {
Name = "TP";
Name = "Teleport";
Help = new string[] {
"&a/client tp [x y z]",
"&a/client teleport [x y z]",
"&eMoves you to the given coordinates.",
};
SingleplayerOnly = true;
}
public override void Execute(string[] args) {

View File

@ -16,6 +16,7 @@ namespace ClassicalSharp.Entities {
public sealed class PhysicsComponent {
bool useLiquidGravity = false; // used by BlockDefinitions.
bool canLiquidJump = true;
internal bool jumping;
internal int multiJumps;
Entity entity;
@ -43,19 +44,45 @@ namespace ClassicalSharp.Entities {
}
if (!jumping) {
return;
canLiquidJump = false; return;
}
bool touchWater = entity.TouchesAnyWater();
bool touchLava = entity.TouchesAnyLava();
if (touchWater || touchLava) {
entity.Velocity.Y += 0.04f;
AABB bounds = entity.Bounds;
int feetY = Utils.Floor(bounds.Min.Y), bodyY = feetY + 1;
int headY = Utils.Floor(bounds.Max.Y);
if (bodyY > headY) bodyY = headY;
bounds.Max.Y = bounds.Min.Y = feetY;
bool liquidFeet = entity.TouchesAny(bounds, touchesLiquid);
bounds.Min.Y = Math.Min(bodyY, headY);
bounds.Max.Y = Math.Max(bodyY, headY);
bool liquidRest = entity.TouchesAny(bounds, touchesLiquid);
bool pastJumpPoint = liquidFeet && !liquidRest && (entity.Position.Y % 1 >= 0.4);
if (!pastJumpPoint) {
canLiquidJump = true;
entity.Velocity.Y += 0.04f;
if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += 0.04f;
if (hacks.HalfSpeeding && hacks.CanSpeed) entity.Velocity.Y += 0.02f;
} else if (pastJumpPoint) {
// either A) jump bob in water B) climb up solid on side
if (collisions.HorizontalCollision)
entity.Velocity.Y += touchLava ? 0.30f : 0.13f;
else if (canLiquidJump)
entity.Velocity.Y += touchLava ? 0.20f : 0.10f;
canLiquidJump = false;
}
} else if (useLiquidGravity) {
entity.Velocity.Y += 0.04f;
if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += 0.04f;
if (hacks.HalfSpeeding && hacks.CanSpeed) entity.Velocity.Y += 0.02f;
canLiquidJump = false;
} else if (entity.TouchesAnyRope()) {
entity.Velocity.Y += (hacks.Speeding && hacks.CanSpeed) ? 0.15f : 0.10f;
canLiquidJump = false;
} else if (entity.onGround) {
DoNormalJump();
}
@ -67,6 +94,7 @@ namespace ClassicalSharp.Entities {
entity.Velocity.Y = jumpVel;
if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += jumpVel;
if (hacks.HalfSpeeding && hacks.CanSpeed) entity.Velocity.Y += jumpVel / 2;
canLiquidJump = false;
}
static Predicate<BlockID> touchesLiquid = IsLiquidCollide;
@ -92,11 +120,11 @@ namespace ClassicalSharp.Entities {
}
if (entity.TouchesAnyWater() && !hacks.Floating) {
MoveNormal(vel, 0.02f * horSpeed, waterDrag, liquidGrav, verSpeed, true);
MoveNormal(vel, 0.02f * horSpeed, waterDrag, liquidGrav, verSpeed);
} else if (entity.TouchesAnyLava() && !hacks.Floating) {
MoveNormal(vel, 0.02f * horSpeed, lavaDrag, liquidGrav, verSpeed, true);
MoveNormal(vel, 0.02f * horSpeed, lavaDrag, liquidGrav, verSpeed);
} else if (entity.TouchesAnyRope() && !hacks.Floating) {
MoveNormal(vel, 0.02f * 1.7f, ropeDrag, ropeGrav, verSpeed, true);
MoveNormal(vel, 0.02f * 1.7f, ropeDrag, ropeGrav, verSpeed);
} else {
float factor = hacks.Floating || entity.onGround ? 0.1f : 0.02f;
float gravity = useLiquidGravity ? liquidGrav : entity.Model.Gravity;
@ -104,7 +132,7 @@ namespace ClassicalSharp.Entities {
if (hacks.Floating) {
MoveFlying(vel, factor * horSpeed, entity.Model.Drag, gravity, verSpeed);
} else {
MoveNormal(vel, factor * horSpeed, entity.Model.Drag, gravity, verSpeed, false);
MoveNormal(vel, factor * horSpeed, entity.Model.Drag, gravity, verSpeed);
}
if (OnIce(entity) && !hacks.Floating) {
@ -161,13 +189,9 @@ namespace ClassicalSharp.Entities {
Move(drag, gravity, yMul);
}
void MoveNormal(Vector3 vel, float factor, Vector3 drag, float gravity, float yMul, bool isLiquid) {
void MoveNormal(Vector3 vel, float factor, Vector3 drag, float gravity, float yMul) {
MoveHor(vel, factor);
if (!isLiquid) {
Move(drag, gravity, yMul);
} else {
MoveLiquid(drag, gravity, yMul);
}
Move(drag, gravity, yMul);
}
void Move(Vector3 drag, float gravity, float yMul) {
@ -180,41 +204,6 @@ namespace ClassicalSharp.Entities {
entity.Velocity = Utils.Mul(entity.Velocity, drag);
entity.Velocity.Y -= gravity;
}
void MoveLiquid(Vector3 drag, float gravity, float yMul) {
entity.Velocity.Y *= yMul;
float addVel = 0;
bool didLiquidJump = false;
if (!hacks.Noclip)
collisions.MoveAndWallSlide();
entity.Position += entity.Velocity;
if (collisions.HorizontalCollision) {
entity.Position += entity.Velocity;
bool pastJumpPoint = !entity.touchesAnyLiq();
entity.Position -= entity.Velocity;
if (!pastJumpPoint) {
didLiquidJump = false;
} else if (pastJumpPoint) {
addVel += 0.3f;
didLiquidJump = true;
}
}
entity.Velocity.Y /= yMul;
if (!didLiquidJump) {
entity.Velocity = Utils.Mul(entity.Velocity, drag);
entity.Velocity.Y -= gravity;
} else {
entity.Velocity.Y = addVel;
addVel = 0;
didLiquidJump = false;
}
}
float GetSpeed(bool canSpeed, float speedMul) {
float factor = hacks.Floating ? speedMul : 1, speed = factor;
@ -272,13 +261,11 @@ namespace ClassicalSharp.Entities {
jumpVel = 0;
if (jumpHeight == 0) return;
if (jumpHeight >= 256) jumpVel = 10.0f;
if (jumpHeight >= 256) jumpVel = 10.0f;
if (jumpHeight >= 512) jumpVel = 16.5f;
if (jumpHeight >= 768) jumpVel = 22.5f;
while (GetMaxHeight(jumpVel) <= jumpHeight) {
jumpVel += 0.001f;
}
while (GetMaxHeight(jumpVel) <= jumpHeight) { jumpVel += 0.001f; }
if (userVel) userJumpVel = jumpVel;
}

View File

@ -90,15 +90,15 @@ namespace ClassicalSharp.Entities {
public Matrix4 TransformMatrix(Vector3 scale, Vector3 pos) {
Matrix4 m = Matrix4.Identity, tmp;
Matrix4.Scale(out tmp, scale.X, scale.Y, scale.Z);
Matrix4.Mult(out m, ref m, ref tmp);
Matrix4.RotateZ(out tmp, -RotZ * Utils.Deg2Rad);
Matrix4.Mult(out m, ref m, ref tmp);
Matrix4.RotateX(out tmp, -RotX * Utils.Deg2Rad);
Matrix4.Mult(out m, ref m, ref tmp);
Matrix4.RotateY(out tmp, -RotY * Utils.Deg2Rad);
Matrix4.Mult(out m, ref m, ref tmp);
Matrix4.Scale(out tmp, scale.X, scale.Y, scale.Z);
Matrix4.Mult(out m, ref m, ref tmp);
Matrix4.Translate(out tmp, pos.X, pos.Y, pos.Z);
Matrix4.Mult(out m, ref m, ref tmp);
@ -209,7 +209,7 @@ namespace ClassicalSharp.Entities {
static bool IsRope(BlockID b) { return b == Block.Rope; }
static readonly Vector3 liqExpand = new Vector3(0.25f/16f, 1.5f/16f, 0.25f/16f);
static readonly Vector3 liqExpand = new Vector3(0.25f/16f, 0/16f, 0.25f/16f);
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are lava or still lava. </summary>
@ -217,12 +217,6 @@ namespace ClassicalSharp.Entities {
// NOTE: Original classic client uses offset (so you can only climb up
// alternating liquid-solid elevators on two sides)
AABB bounds = Bounds.Offset(liqExpand);
if (this.Model.liquidOffset) {
float humanSize = 28.1f/16f; //TODO: Actually get the height of a human.
float mAdj = bounds.Height / humanSize;
bounds.Min.Y += (5f/16f * mAdj);
bounds.Max.Y -= (6f/16f * mAdj);
}
return TouchesAny(bounds, touchesAnyLava);
}
static Predicate<BlockID> touchesAnyLava = IsLava;
@ -232,31 +226,9 @@ namespace ClassicalSharp.Entities {
/// bounding box of this entity are water or still water. </summary>
public bool TouchesAnyWater() {
AABB bounds = Bounds.Offset(liqExpand);
if (this.Model.liquidOffset) {
float humanSize = 28.1f/16f; //TODO: Actually get the height of a human.
float mAdj = bounds.Height / humanSize;
bounds.Min.Y += (5f/16f * mAdj);
bounds.Max.Y -= (6f/16f * mAdj);
}
return TouchesAny(bounds, touchesAnyWater);
}
static Predicate<BlockID> touchesAnyWater = IsWater;
static bool IsWater(BlockID b) { return BlockInfo.ExtendedCollide[b] == CollideType.LiquidWater; }
public bool touchesAnyLiq() {
AABB bounds = this.Bounds.Offset(liqExpand);
if (this.Model.liquidOffset) {
float humanSize = 28.1f/16f; //TODO: Actually get the height of a human.
float mAdj = bounds.Height / humanSize;
bounds.Min.Y += (5f/16f * mAdj);
bounds.Max.Y -= (6f/16f * mAdj);
}
return TouchesAny(bounds, touchesLiquid);
}
static Predicate<BlockID> touchesLiquid = IsLiquidCollide;
static bool IsLiquidCollide(BlockID block) { return BlockInfo.Collide[block] == CollideType.Liquid; }
}
}

View File

@ -75,8 +75,6 @@ namespace ClassicalSharp.Model {
/// <summary> Scaling factor applied, multiplied by the entity's current model scale. </summary>
public float NameScale = 1.0f;
public bool liquidOffset = true;
/// <summary> The size of the bounding box that is used when
/// performing collision detection for this model. </summary>