Save a few kilobytes of memory in Level instances

This commit is contained in:
UnknownShadow200 2023-11-18 21:27:17 +11:00
parent 8c9f0e60ea
commit b72579bd18
6 changed files with 77 additions and 92 deletions

View File

@ -51,23 +51,31 @@ namespace MCGalaxy.Blocks {
return null; return null;
} }
// NOTE: These static declarations are just to save a few memory allocations
// Behind the scenes, 'return XYZ;' is actually compiled into 'return new HandleDelete(XYZ);'
// So by declaring a static variable, 'new HandleDelete(XYZ)' is only ever called once
// instead of over and over - thereby slightly reducing memory usage
static HandleDelete DB_revert = DeleteBehaviour.RevertDoor;
static HandleDelete DB_oDoor = DeleteBehaviour.oDoor;
static HandleDelete DB_Door = DeleteBehaviour.Door;
/// <summary> Retrieves the default delete block handler for the given block. </summary> /// <summary> Retrieves the default delete block handler for the given block. </summary>
internal static HandleDelete GetDeleteHandler(BlockID block, BlockProps[] props) { internal static HandleDelete GetDeleteHandler(BlockID block, BlockProps[] props) {
switch (block) { switch (block) {
case Block.RocketStart: return DeleteBehaviour.RocketStart; case Block.RocketStart: return DeleteBehaviour.RocketStart;
case Block.Fireworks: return DeleteBehaviour.Firework; case Block.Fireworks: return DeleteBehaviour.Firework;
case Block.C4Detonator: return DeleteBehaviour.C4Det; case Block.C4Detonator: return DeleteBehaviour.C4Det;
case Block.Door_Log_air: return DeleteBehaviour.RevertDoor; case Block.Door_Log_air: return DB_revert;
case Block.Door_TNT_air: return DeleteBehaviour.RevertDoor; case Block.Door_TNT_air: return DB_revert;
case Block.Door_Green_air: return DeleteBehaviour.RevertDoor; case Block.Door_Green_air: return DB_revert;
} }
// NOTE: If this gets changed, make sure to change BlockOptions.cs too // NOTE: If this gets changed, make sure to change BlockOptions.cs too
if (props[block].IsMessageBlock) return DeleteBehaviour.DoMessageBlock; if (props[block].IsMessageBlock) return DeleteBehaviour.DoMessageBlock;
if (props[block].IsPortal) return DeleteBehaviour.DoPortal; if (props[block].IsPortal) return DeleteBehaviour.DoPortal;
if (props[block].IsTDoor) return DeleteBehaviour.RevertDoor; if (props[block].IsTDoor) return DB_revert;
if (props[block].oDoorBlock != Block.Invalid) return DeleteBehaviour.oDoor; if (props[block].oDoorBlock != Block.Invalid) return DB_oDoor;
if (props[block].IsDoor) return DeleteBehaviour.Door; if (props[block].IsDoor) return DB_Door;
return null; return null;
} }
@ -87,12 +95,17 @@ namespace MCGalaxy.Blocks {
} }
// See comments noted above for reasoning behind static declaration of some HandleDelete handlers
static HandlePhysics PH_do_Door = DoorPhysics.Do;
static HandlePhysics PH_do_oDoor = DoorPhysics.oDoor;
static HandlePhysics PH_do_Other = OtherPhysics.DoOther;
/// <summary> Retrieves the default physics block handler for the given block. </summary> /// <summary> Retrieves the default physics block handler for the given block. </summary>
internal static HandlePhysics GetPhysicsHandler(BlockID block, BlockProps[] props) { internal static HandlePhysics GetPhysicsHandler(BlockID block, BlockProps[] props) {
switch (block) { switch (block) {
case Block.Door_Log_air: return DoorPhysics.Do; case Block.Door_Log_air: return PH_do_Door;
case Block.Door_TNT_air: return DoorPhysics.Do; case Block.Door_TNT_air: return PH_do_Door;
case Block.Door_Green_air: return DoorPhysics.Do; case Block.Door_Green_air: return PH_do_Door;
case Block.SnakeTail: return SnakePhysics.DoTail; case Block.SnakeTail: return SnakePhysics.DoTail;
case Block.Snake: return SnakePhysics.Do; case Block.Snake: return SnakePhysics.Do;
@ -156,25 +169,25 @@ namespace MCGalaxy.Blocks {
HandlePhysics animalAI = AnimalAIHandler(props[block].AnimalAI); HandlePhysics animalAI = AnimalAIHandler(props[block].AnimalAI);
if (animalAI != null) return animalAI; if (animalAI != null) return animalAI;
if (props[block].oDoorBlock != Block.Invalid) return DoorPhysics.oDoor; if (props[block].oDoorBlock != Block.Invalid) return PH_do_oDoor;
if (props[block].GrassBlock != Block.Invalid) return OtherPhysics.DoDirtGrow; if (props[block].GrassBlock != Block.Invalid) return OtherPhysics.DoDirtGrow;
if (props[block].DirtBlock != Block.Invalid) return OtherPhysics.DoGrassDie; if (props[block].DirtBlock != Block.Invalid) return OtherPhysics.DoGrassDie;
// TODO: should this be checking WaterKills/LavaKills // TODO: should this be checking WaterKills/LavaKills
// Adv physics updating anything placed next to water or lava // Adv physics updating anything placed next to water or lava
if ((block >= Block.Red && block <= Block.RedMushroom) || block == Block.Wood || block == Block.Log || block == Block.Bookshelf) { if ((block >= Block.Red && block <= Block.RedMushroom) || block == Block.Wood || block == Block.Log || block == Block.Bookshelf) {
return OtherPhysics.DoOther; return PH_do_Other;
} }
return null; return null;
} }
/// <summary> Retrieves the default physics block handler for the given block. </summary> /// <summary> Retrieves the default physics block handler for the given block. </summary>
internal static HandlePhysics GetPhysicsDoorsHandler(BlockID block, BlockProps[] props) { internal static HandlePhysics GetPhysicsDoorsHandler(BlockID block, BlockProps[] props) {
if (block == Block.Air) return DoorPhysics.Do; if (block == Block.Air) return PH_do_Door;
if (block == Block.Door_Log_air) return DoorPhysics.Do; if (block == Block.Door_Log_air) return PH_do_Door;
if (block == Block.Door_TNT_air) return DoorPhysics.Do; if (block == Block.Door_TNT_air) return PH_do_Door;
if (block == Block.Door_Green_air) return DoorPhysics.Do; if (block == Block.Door_Green_air) return PH_do_Door;
if (props[block].oDoorBlock != Block.Invalid) return DoorPhysics.oDoor; if (props[block].oDoorBlock != Block.Invalid) return PH_do_oDoor;
return null; return null;
} }

View File

@ -24,6 +24,7 @@ namespace MCGalaxy.Commands.Misc {
public override string name { get { return "Ride"; } } public override string name { get { return "Ride"; } }
public override string type { get { return CommandTypes.Other; } } public override string type { get { return CommandTypes.Other; } }
public override bool museumUsable { get { return false; } } public override bool museumUsable { get { return false; } }
public override bool SuperUseable { get { return false; } }
public override void Use(Player p, string message, CommandData data) { public override void Use(Player p, string message, CommandData data) {
p.onTrain = !p.onTrain; p.onTrain = !p.onTrain;

View File

@ -15,15 +15,6 @@ using SQLiteErrorCode = System.Int32;
namespace MCGalaxy.SQL namespace MCGalaxy.SQL
{ {
enum SqlType
{
Single, Double, Decimal,
SByte, Int16, Int32, Int64,
Byte, UInt16, UInt32, UInt64,
Boolean, DateTime,
Binary, String, Object,
}
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
static class Interop static class Interop
{ {
@ -410,38 +401,6 @@ namespace MCGalaxy.SQL
Thread.Sleep((int)(seed % 150) + 1); Thread.Sleep((int)(seed % 150) + 1);
} }
} }
internal static SqlType TypeToDbType(Type typ) {
TypeCode tc = Type.GetTypeCode(typ);
if (tc == TypeCode.Object) {
if (typ == typeof(byte[])) return SqlType.Binary;
return SqlType.String;
}
return type_to_dbtype[(int)tc];
}
static SqlType[] type_to_dbtype = {
SqlType.Object, // Empty (0)
SqlType.Binary, // Object (1)
SqlType.Object, // DBNull (2)
SqlType.Boolean, // Boolean (3)
SqlType.SByte, // Char (4)
SqlType.SByte, // SByte (5)
SqlType.Byte, // Byte (6)
SqlType.Int16, // Int16 (7)
SqlType.UInt16, // UInt16 (8)
SqlType.Int32, // Int32 (9)
SqlType.UInt32, // UInt32 (10)
SqlType.Int64, // Int64 (11)
SqlType.UInt64, // UInt64 (12)
SqlType.Single, // Single (13)
SqlType.Double, // Double (14)
SqlType.Decimal, // Decimal (15)
SqlType.DateTime, // DateTime (16)
SqlType.Object, // ?? (17)
SqlType.String // String (18)
};
} }
enum TypeAffinity enum TypeAffinity
@ -772,35 +731,41 @@ namespace MCGalaxy.SQL
return Interop.sqlite3_bind_null(handle, i); return Interop.sqlite3_bind_null(handle, i);
} }
SqlType type = SQLiteConvert.TypeToDbType(obj.GetType()); Type t = obj.GetType();
switch (type) { TypeCode tc = Type.GetTypeCode(t);
case SqlType.DateTime:
return Bind_DateTime(i, Convert.ToDateTime(obj, CultureInfo.InvariantCulture)); // byte[] doesn't have its own typecode, so needs special handling here
case SqlType.Boolean: if (tc == TypeCode.Object && t == typeof(byte[])) {
return Bind_Int32(i, Convert.ToBoolean(obj) ? 1 : 0); byte[] b = (byte[])obj;
case SqlType.SByte: return Interop.sqlite3_bind_blob(handle, i, b, b.Length, (IntPtr)(-1));
}
switch (tc) {
case TypeCode.DateTime:
return Bind_DateTime(i, (DateTime)obj);
case TypeCode.Boolean:
return Bind_Int32(i, ((bool)obj) ? 1 : 0);
case TypeCode.Char: // TODO ushort instead?
case TypeCode.SByte:
return Bind_Int32(i, Convert.ToSByte(obj)); return Bind_Int32(i, Convert.ToSByte(obj));
case SqlType.Int16: case TypeCode.Int16:
return Bind_Int32(i, Convert.ToInt16(obj)); return Bind_Int32(i, Convert.ToInt16(obj));
case SqlType.Int32: case TypeCode.Int32:
return Bind_Int32(i, Convert.ToInt32(obj)); return Bind_Int32(i, Convert.ToInt32(obj));
case SqlType.Int64: case TypeCode.Int64:
return Bind_Int64(i, Convert.ToInt64(obj)); return Bind_Int64(i, Convert.ToInt64(obj));
case SqlType.Byte: case TypeCode.Byte:
return Bind_Int32(i, Convert.ToByte(obj)); return Bind_Int32(i, Convert.ToByte(obj));
case SqlType.UInt16: case TypeCode.UInt16:
return Bind_Int32(i, Convert.ToUInt16(obj)); return Bind_Int32(i, Convert.ToUInt16(obj));
case SqlType.UInt32: case TypeCode.UInt32:
return Bind_Int32(i, (int)Convert.ToUInt32(obj)); return Bind_Int32(i, (int)Convert.ToUInt32(obj));
case SqlType.UInt64: case TypeCode.UInt64:
return Bind_Int64(i, (long)Convert.ToUInt64(obj)); return Bind_Int64(i, (long)Convert.ToUInt64(obj));
case SqlType.Single: case TypeCode.Single:
case SqlType.Double: case TypeCode.Double:
case SqlType.Decimal: case TypeCode.Decimal:
return Interop.sqlite3_bind_double(handle, i, Convert.ToDouble(obj)); return Interop.sqlite3_bind_double(handle, i, Convert.ToDouble(obj));
case SqlType.Binary:
byte[] b = (byte[])obj;
return Interop.sqlite3_bind_blob(handle, i, b, b.Length, (IntPtr)(-1));
default: default:
return Bind_Text(i, obj.ToString()); return Bind_Text(i, obj.ToString());
} }

View File

@ -134,7 +134,7 @@ namespace MCGalaxy {
public bool staticCommands; public bool staticCommands;
internal DateTime lastAccessStatus; internal DateTime lastAccessStatus;
public VolatileArray<SchedulerTask> CriticalTasks = new VolatileArray<SchedulerTask>(); public VolatileArray<SchedulerTask> CriticalTasks;
public bool isFlying; public bool isFlying;
public bool aiming; public bool aiming;
@ -174,7 +174,7 @@ namespace MCGalaxy {
} }
// BlockDefinitions // BlockDefinitions
internal int gbStep = 0, lbStep = 0; internal int gbStep, lbStep;
internal BlockDefinition gbBlock, lbBlock; internal BlockDefinition gbBlock, lbBlock;
//Undo //Undo
@ -221,7 +221,7 @@ namespace MCGalaxy {
internal DateTime cmdUnblocked; internal DateTime cmdUnblocked;
List<DateTime> partialLog; List<DateTime> partialLog;
public WarpList Waypoints = new WarpList(); public WarpList Waypoints;
public DateTime LastPatrol; public DateTime LastPatrol;
public LevelPermission Rank { get { return group.Permission; } } public LevelPermission Rank { get { return group.Permission; } }

View File

@ -27,6 +27,7 @@ using MCGalaxy.Games;
using MCGalaxy.Maths; using MCGalaxy.Maths;
using MCGalaxy.Network; using MCGalaxy.Network;
using MCGalaxy.SQL; using MCGalaxy.SQL;
using MCGalaxy.Tasks;
using BlockID = System.UInt16; using BlockID = System.UInt16;
namespace MCGalaxy { namespace MCGalaxy {
@ -68,6 +69,9 @@ namespace MCGalaxy {
Session = session; Session = session;
SetIP(Socket.IP); SetIP(Socket.IP);
CriticalTasks = new VolatileArray<SchedulerTask>();
Waypoints = new WarpList();
spamChecker = new SpamChecker(this); spamChecker = new SpamChecker(this);
partialLog = new List<DateTime>(20); partialLog = new List<DateTime>(20);
session.ID = Interlocked.Increment(ref sessionCounter) & SESSION_ID_MASK; session.ID = Interlocked.Increment(ref sessionCounter) & SESSION_ID_MASK;

View File

@ -65,14 +65,14 @@ namespace MCGalaxy.Authentication
public abstract class PassAuthenticator : ExtraAuthenticator public abstract class PassAuthenticator : ExtraAuthenticator
{ {
public override void RequiresVerification(Player p, string action) { public override void RequiresVerification(Player p, string action) {
p.Message("&WYou must first verify with &T/Pass [Password] &Wbefore you can {0}", action); p.Message("&WYou must first verify with &T/Pass [password] &Wbefore you can {0}", action);
} }
public override void NeedVerification(Player p) { public override void NeedVerification(Player p) {
if (!HasPassword(p.name)) { if (!HasPassword(p.name)) {
p.Message("&WPlease set your account verification password with &T/SetPass [password]!"); p.Message("&WPlease set your account verification password with &T/SetPass [password]");
} else { } else {
p.Message("&WPlease complete account verification with &T/Pass [password]!"); p.Message("&WPlease complete account verification with &T/Pass [password]");
} }
} }
@ -158,7 +158,7 @@ namespace MCGalaxy.Authentication
if (password.IndexOf(' ') >= 0) { p.Message("Your password must be &Wone &Sword!"); return; } if (password.IndexOf(' ') >= 0) { p.Message("Your password must be &Wone &Sword!"); return; }
if (!HasPassword(p.name)) { if (!HasPassword(p.name)) {
p.Message("You have not &Wset a password, &Suse &T/SetPass [Password] &Wto set one"); p.Message("You have not &Wset a verification password yet, &Suse &T/SetPass [password] &Wto set one");
p.Message("Make sure to use a different password than your Minecraft one!"); p.Message("Make sure to use a different password than your Minecraft one!");
return; return;
} }
@ -173,14 +173,16 @@ namespace MCGalaxy.Authentication
void DoSetPassword(Player p, string password) { void DoSetPassword(Player p, string password) {
if (p.Unverified && HasPassword(p.name)) { if (p.Unverified && HasPassword(p.name)) {
RequiresVerification(p, "can change your password"); RequiresVerification(p, "can change your verification password");
p.Message("Forgot your password? Contact &W{0} &Sto &Wreset it.", Server.Config.OwnerName); p.Message("Forgot your password? Contact &W{0} &Sto &Wreset it.", Server.Config.OwnerName);
return; return;
} }
if (password.IndexOf(' ') >= 0) {
p.Message("&WPassword must be one word."); return;
}
if (password.IndexOf(' ') >= 0) { p.Message("&WPassword must be one word."); return; }
StorePassword(p.name, password); StorePassword(p.name, password);
p.Message("Your password was &aset to: &c" + password); p.Message("Your verification password was &aset to: &c" + password);
} }
void DoResetPassword(Player p, string name, CommandData data) { void DoResetPassword(Player p, string name, CommandData data) {
@ -188,19 +190,19 @@ namespace MCGalaxy.Authentication
if (target == null) return; if (target == null) return;
if (p.Unverified) { if (p.Unverified) {
RequiresVerification(p, "can reset passwords"); RequiresVerification(p, "can reset verification passwords");
return; return;
} }
if (data.Rank < Server.Config.ResetPasswordRank) { if (data.Rank < Server.Config.ResetPasswordRank) {
p.Message("Only {0}&S+ can reset passwords", p.Message("Only {0}&S+ can reset verification passwords",
Group.GetColoredName(Server.Config.ResetPasswordRank)); Group.GetColoredName(Server.Config.ResetPasswordRank));
return; return;
} }
if (ResetPassword(target)) { if (ResetPassword(target)) {
p.Message("Reset password for {0}", p.FormatNick(target)); p.Message("Reset verification password for {0}", p.FormatNick(target));
} else { } else {
p.Message("{0} &Sdoes not have a password.", p.FormatNick(target)); p.Message("{0} &Sdoes not have a verification password.", p.FormatNick(target));
} }
} }