That's not exactly my database design, but it's close. It's actually two tables that ever store information about the weapons. I have one table with 'kills' where each time someone kills someone else I store the id of the attacker, the id of the victim and the id of the weapon that was used (amongst some other data). In this case, there's always just one weapon so here I could use regular weapon ids of 0,1,2,3,4 etc.
Then I also have a table that stores restrictions for every game server. Some weapons are not allowed to be used; however there is no way for anyone to control that from within the game, so these kind of tools simply check if a kill was made with a restricted weapon and warn (eventually 'kick') the attacker.
My app can control multiple game servers and each entry in the Restrictions table correspond to one of those servers. The Restrictions table thus has columns ServerId and Weapons, where this time Weapons should be a bitwise combination of all the restricted weapons on that server. This is where I need the bitmasked values so the weapon Ids need to be 1,2,4,8,etc. And this is where I run into trouble because there are simply not enough powers of two in the integer/long types.
If I had a boolean column for every weapon that would mean the Restrictions table would get over 85 columns; I think that's a bit much.
Finally, the weapons themselves are not in the database, I define and add them in code. The reason is that, so far at least, no changes in the weapons have been made to the game (so I don't think I'll ever need to change them) and more importantly, a change in the weapons would require a new build anyway.
Ok, so far I have to viable solutions:
1. Use a binary string where each character represents the restricted state of a weapon,
2. Use the BigInteger and store the result as text in the database.
Which is the most efficient / fast method? My app is reading new log lines every 5 seconds, and it might get as much as 50 new lines in that time. If all of those are Kill/Damage events (damage events are just when someone gets shot but not deadly yet) then I would need to check if a weapon is restricted 50 times in a row. Handling one such event thus should take no longer than 0.1 second.
My code that handles a Kill event (a Damage event is similar except using a different table) is basically:
The IsWeaponRestricted method when I decide to use option 1 would be something likeCode:Dim attacker As Player = GetAttacker() Dim victim As Player = GetPlayer() Dim weapon As Weapon = ParseWeapon(code) Dim kill As New Kill(attacker, victim, weapon) KillManager.Instance.Save(kill) If Restrictions.IsWeaponRestricted(weapon) Then MessageManager.WarnPlayer(player, weapon) End If
For option 2 I guess it would look likeCode:Public Shared Function IsWeaponRestricted(weapon As Weapon) As Boolean Dim restricted As String = Me.Server.Restrictions.Weapons 'the binary string Return restricted(weapon.Id) = "1" End Function
So option 1 is merely finding a character at a specified index while option 2 needs to parse a string into a BigInteger and then use bitwise logic. At a guess I would say option 1 is faster, but I might be underestimating the BigInteger, I've never used it...Code:Public Shared Function IsWeaponRestricted(weapon As Weapon) As Boolean Dim restricted As String = Me.Server.Restrictions.Weapons 'the BigInteger string Dim int As BigInteger = BigInteger.Parse(restricted) Return (int And weapon.Id) = weapon.Id End Function
I'll test this as soon as I can (at the moment my project doesn't build), but maybe someone has some thoughts about this?




Reply With Quote