aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Pickering <alexandermpickering@gmail.com>2016-07-10 17:04:29 -0400
committerAlexander Pickering <alexandermpickering@gmail.com>2016-07-10 17:04:29 -0400
commit1de5f9ac6f038bfed2230cc1272b253794b2f41a (patch)
tree15bc9d515f1f48c036522afb7cc71f60243849a9
downloadartery-1de5f9ac6f038bfed2230cc1272b253794b2f41a.tar.gz
artery-1de5f9ac6f038bfed2230cc1272b253794b2f41a.tar.bz2
artery-1de5f9ac6f038bfed2230cc1272b253794b2f41a.zip
Initial commit
-rw-r--r--LISCENSE0
-rw-r--r--artery.txt10
-rw-r--r--entities/entities/art_chest/cl_init.lua53
-rw-r--r--entities/entities/art_chest/init.lua72
-rw-r--r--entities/entities/art_chest/shared.lua2
-rw-r--r--entities/entities/npc_townie/cl_init.lua66
-rw-r--r--entities/entities/npc_townie/init.lua75
-rw-r--r--entities/entities/npc_townie/shared.lua123
-rw-r--r--entities/weapons/hands.lua142
-rw-r--r--gamemode/autolua.lua44
-rw-r--r--gamemode/cl_init.lua1
-rw-r--r--gamemode/client/cl_inventory.lua199
-rw-r--r--gamemode/client/cl_pac.lua2
-rw-r--r--gamemode/client/cl_systems.lua4
-rw-r--r--gamemode/client/vgui/vgui_DMultiModelPanel.lua161
-rw-r--r--gamemode/init.lua5
-rw-r--r--gamemode/server/heatmap.lua141
-rw-r--r--gamemode/server/sv_config.lua19
-rw-r--r--gamemode/server/sv_database.lua155
-rw-r--r--gamemode/server/sv_loadplayer.lua15
-rw-r--r--gamemode/server/sv_mapconfig.lua19
-rw-r--r--gamemode/server/sv_pac.lua28
-rw-r--r--gamemode/server/sv_systems.lua21
-rw-r--r--gamemode/server/systems/health.lua12
-rw-r--r--gamemode/server/test/testfile.lua48
-rw-r--r--gamemode/shared.lua14
-rw-r--r--gamemode/shared/aes.lua526
-rw-r--r--gamemode/shared/concommands.lua28
-rw-r--r--gamemode/shared/fuzzel.lua286
-rw-r--r--gamemode/shared/inventory.lua213
-rw-r--r--gamemode/shared/inventory_common.lua205
-rw-r--r--gamemode/shared/itemcommon/common_inventory.lua9
-rw-r--r--gamemode/shared/itemsystem/exampleitem.lua25
-rw-r--r--gamemode/shared/itemsystem/scrapgun.lua60
-rw-r--r--gamemode/shared/loaditems.lua55
-rw-r--r--gamemode/shared/lockbox/array.lua211
-rw-r--r--gamemode/shared/lockbox/base64.lua157
-rw-r--r--gamemode/shared/lockbox/bit.lua11
-rw-r--r--gamemode/shared/lockbox/ecb.lua191
-rw-r--r--gamemode/shared/lockbox/padding.lua21
-rw-r--r--gamemode/shared/lockbox/queue.lua47
-rw-r--r--gamemode/shared/lockbox/stream.lua112
-rw-r--r--gamemode/shared/sh_setup.lua165
-rw-r--r--gamemode/shared/sparkel.lua17
44 files changed, 3770 insertions, 0 deletions
diff --git a/LISCENSE b/LISCENSE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/LISCENSE
diff --git a/artery.txt b/artery.txt
new file mode 100644
index 0000000..dceec9f
--- /dev/null
+++ b/artery.txt
@@ -0,0 +1,10 @@
+"artery"
+{
+ "base" "base"
+ "title" "Artery"
+ "menusystem" "1"
+ "maps" "^rp_"
+ "settings"
+ {
+ }
+}
diff --git a/entities/entities/art_chest/cl_init.lua b/entities/entities/art_chest/cl_init.lua
new file mode 100644
index 0000000..072d421
--- /dev/null
+++ b/entities/entities/art_chest/cl_init.lua
@@ -0,0 +1,53 @@
+include('shared.lua')
+local invfuncs = include("../../../gamemode/shared/inventory_common.lua")
+
+ENT.RenderGroup = RENDERGROUP_BOTH
+
+function ENT:Initialize()
+end
+
+function ENT:OnRemove()
+end
+
+function ENT:Think()
+end
+
+function ENT:Draw()
+
+ self:DrawModel()
+end
+
+local oldpanel = nil
+net.Receive("openchestinv",function(len,ply)
+ if oldpanel ~= nil then oldpanel:Remove() end
+ print("Opening chest inventory")
+ local what = net.ReadEntity()
+ local chest = invfuncs.DeSerializeBackpack()
+ ShowInventory()
+ local dat = {}
+ dat.redraw = function()
+ net.Start("requestchestinv")
+ net.WriteEntity(what)
+ net.SendToServer()
+ end
+ dat.panel = vgui.Create( "DFrame" )
+ oldpanel = dat.panel
+ dat.panel.OnClose = function()
+ net.Start("closechestinv")
+ net.WriteEntity(what)
+ net.SendToServer()
+ end
+ table.insert(LocalPlayer().invdisplays,dat)
+ local width = ScrW()
+ local height = ScrH()
+ local invpanel = dat.panel
+ invpanel:SetPos( width - (width/4), 0 )
+ invpanel:SetSize( width / 4, height )
+ invpanel:SetTitle( "Chest" )
+ invpanel:SetDraggable( true )
+ invpanel:MakePopup()
+ local innerpanel = vgui.Create("DPanel",dat.panel)
+ innerpanel:Dock(FILL)
+ innerpanel.Paint = function( self, w, h ) draw.RoundedBox( 4, 0, 0, w, h, Color( 157, 160, 167 ) ) end
+ invfuncs.DrawBackpackOnDPanel(innerpanel, chest, 1, what)
+end)
diff --git a/entities/entities/art_chest/init.lua b/entities/entities/art_chest/init.lua
new file mode 100644
index 0000000..92d1371
--- /dev/null
+++ b/entities/entities/art_chest/init.lua
@@ -0,0 +1,72 @@
+AddCSLuaFile( "cl_init.lua" )
+AddCSLuaFile( "shared.lua" )
+
+include("shared.lua")
+local invfuncs = include("../../../gamemode/shared/inventory_common.lua")
+
+function ENT:Initialize()
+ self.Openedby = {}
+ self:SetModel("models/props_junk/Rock001a.mdl")
+ self:PhysicsInit( SOLID_VPHYSICS )
+ self:SetMoveType( MOVETYPE_NONE )
+ self:SetSolid( SOLID_VPHYSICS )
+ self:SetCollisionGroup( COLLISION_GROUP_INTERACTIVE )
+ self:SetUseType(SIMPLE_USE)
+
+ local phys = self:GetPhysicsObject()
+ self.Inventory = {}
+ self.Inventory.Backpacks = {}
+ self.Inventory.Backpacks[1] = invfuncs.CreateBackpack("Chest",3,3)
+
+ phys:EnableMotion(false)
+ phys:Sleep()
+
+ self.StoredItems = {}
+end
+
+util.AddNetworkString("openchestinv")
+util.AddNetworkString("closechestinv")
+util.AddNetworkString("requestchestinv")
+
+net.Receive("requestchestinv",function(ln,ply)
+ print("Received request for chest")
+ local chest = net.ReadEntity()
+ print("Chest:",chest)
+ chest:SendInventory(ply)
+end)
+
+net.Receive("closechestinv",function(ln,ply)
+ local chest = net.ReadEntity()
+ print("closeing chest of ", ply,chest)
+ chest.Openedby[ply] = nil
+end)
+
+function ENT:SendInventory(towho)
+ print("Sending inventory to",towho,type(towho))
+ if type(towho) == "table" then
+ print("who:")
+ PrintTable(towho)
+ print("opendby:")
+ PrintTable(self.Openedby)
+ assert(#towho != 0,"Sending inventory to no players!")
+ else
+ print("towho is not a table!")
+ self.Openedby[towho] = true
+ end
+ print("about to start net message")
+ net.Start("openchestinv")
+ net.WriteEntity(self)
+ invfuncs.SerializeBackpack(self.Inventory.Backpacks[1])
+ net.Send(towho)
+end
+
+function ENT:SynchronizeInventory()
+ print("Entity synchronize called")
+ self:SendInventory(table.GetKeys(self.Openedby))
+end
+
+function ENT:Use(ply)
+ print("Ply opened:",ply)
+ self.Openedby[ply] = true
+ self:SendInventory(ply)
+end
diff --git a/entities/entities/art_chest/shared.lua b/entities/entities/art_chest/shared.lua
new file mode 100644
index 0000000..0038793
--- /dev/null
+++ b/entities/entities/art_chest/shared.lua
@@ -0,0 +1,2 @@
+ENT.Type = "anim"
+ENT.Base = "base_anim"
diff --git a/entities/entities/npc_townie/cl_init.lua b/entities/entities/npc_townie/cl_init.lua
new file mode 100644
index 0000000..f941737
--- /dev/null
+++ b/entities/entities/npc_townie/cl_init.lua
@@ -0,0 +1,66 @@
+include('shared.lua')
+
+ENT.RenderGroup = RENDERGROUP_BOTH
+
+/*---------------------------------------------------------
+ Name: Draw
+ Desc: Draw it!
+---------------------------------------------------------*/
+function ENT:Draw()
+ self:DrawModel()
+end
+
+/*---------------------------------------------------------
+ Name: DrawTranslucent
+ Desc: Draw translucent
+---------------------------------------------------------*/
+function ENT:DrawTranslucent()
+
+ // This is here just to make it backwards compatible.
+ // You shouldn't really be drawing your model here unless it's translucent
+
+ self:Draw()
+
+end
+
+/*---------------------------------------------------------
+ Name: BuildBonePositions
+ Desc:
+---------------------------------------------------------*/
+function ENT:BuildBonePositions( NumBones, NumPhysBones )
+
+ // You can use this section to position the bones of
+ // any animated model using self:SetBonePosition( BoneNum, Pos, Angle )
+
+ // This will override any animation data and isn't meant as a
+ // replacement for animations. We're using this to position the limbs
+ // of ragdolls.
+
+end
+
+
+
+/*---------------------------------------------------------
+ Name: SetRagdollBones
+ Desc:
+---------------------------------------------------------*/
+function ENT:SetRagdollBones( bIn )
+
+ // If this is set to true then the engine will call
+ // DoRagdollBone (below) for each ragdoll bone.
+ // It will then automatically fill in the rest of the bones
+
+ self.m_bRagdollSetup = bIn
+
+end
+
+
+/*---------------------------------------------------------
+ Name: DoRagdollBone
+ Desc:
+---------------------------------------------------------*/
+function ENT:DoRagdollBone( PhysBoneNum, BoneNum )
+
+ // self:SetBonePosition( BoneNum, Pos, Angle )
+
+end
diff --git a/entities/entities/npc_townie/init.lua b/entities/entities/npc_townie/init.lua
new file mode 100644
index 0000000..aa0f007
--- /dev/null
+++ b/entities/entities/npc_townie/init.lua
@@ -0,0 +1,75 @@
+
+AddCSLuaFile( "cl_init.lua" )
+AddCSLuaFile( "shared.lua" )
+
+include('shared.lua')
+
+function ENT:Initialize()
+ --print("NPC spawned!")
+ --self:SetMoveType(MOVETYPE_STEP)
+ self:SetSolid(SOLID_OBB)
+ --self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
+
+ if(self.Model) then self:SetModel(self.Model)
+ else print("NPC created without model, this might be a bug!") end
+ if(not self.Stats) then
+ print("NPC created without any stats, this is a bug!")
+ return
+ end
+ if(self.Stats["Vitality"]) then
+ self:SetHealth(self.Stats["Vitality"])
+ else print("NPC created with no stat for vitality, this might be a bug!")end
+ if(self.Stats["Accel"]) then self.loco:SetAcceleration(self.Stats["Accel"])end
+ if(self.Stats["Decel"]) then self.loco:SetDeceleration(self.Stats["Decel"]) end
+ if(self.Stats["Step"]) then self.loco:SetJumpHeight(self.Stats["Step"]) end
+ if(self.OnSpawn) then self:OnSpawn() end
+ --self:SetModel( "models/Humans/Group01/Female_01.mdl" )
+ --[[
+ self:SetHullType( HULL_HUMAN );
+ self:SetHullSizeNormal();
+
+ self:SetSolid( SOLID_BBOX )
+ self:SetMoveType( MOVETYPE_STEP )
+
+ self:CapabilitiesAdd( CAP_MOVE_GROUND or CAP_OPEN_DOORS or CAP_ANIMATEDFACE or CAP_TURN_HEAD or CAP_USE_SHOT_REGULATOR or CAP_AIM_GUN )
+
+ self:SetMaxYawSpeed( 5000 )
+ ]]--
+end
+
+function ENT:OnInjured(dmg)
+ --print("Taking some dammage")
+ local itempos = self:GetPos()
+ --print("Takeing " .. dmg:GetDamage() .. " health from our " .. self:Health())
+ --self:SetHealth(self:Health() - dmg:GetDamage())
+ --print("Health is now" .. self:Health())
+ if self.OnDammage != nil then self:OnDammage(dmg) end
+end
+
+function ENT:OnContact(ent)
+ if(ent:GetClass() == "ws_arrow") then
+ self:TakeDamage(30)
+ ent:SetParent(self)
+ end
+end
+
+function ENT:OnKilled(dmg)
+ if(CLIENT) then return end
+ if not self.Drops then return end
+ --print("Looks like we have some drops")
+ for k,v in pairs(self.Drops) do
+ local rng = math.random(0,100)
+ local itemname = self.Drops[k][1]
+ local itemchance = self.Drops[k][2]
+ local heightoffset = 10
+ if rng < itemchance then
+ local drop = ents.Create("ws_item")
+ drop.Item = GetItemByName(itemname)
+ drop:SetModel(drop.Item.Model)
+ drop:SetPos(self:GetPos() + (self:GetUp()*heightoffset))
+ drop:Spawn()
+ heightoffset = heightoffset + 10
+ end
+ end
+ self:BecomeRagdoll( dmg )
+end
diff --git a/entities/entities/npc_townie/shared.lua b/entities/entities/npc_townie/shared.lua
new file mode 100644
index 0000000..3662edd
--- /dev/null
+++ b/entities/entities/npc_townie/shared.lua
@@ -0,0 +1,123 @@
+ENT.Base = "base_nextbot"
+
+//WS stuff
+ENT.Drops = nil
+ENT.OnDammage = nil
+ENT.Speed = 0
+ENT.Model = nil
+
+ENT.Behave = nil
+ENT.Act = nil
+
+/*---------------------------------------------------------
+ Name: OnRemove
+ Desc: Called just before entity is deleted
+---------------------------------------------------------*/
+function ENT:OnRemove()
+end
+
+--[[
+function ENT:DefaultBehaviour()
+ while ( true ) do
+ --Main loop for ai
+ --print("Going into behavior for " .. self.Name)
+ --Update aware enemies
+ local players = ents.FindByClass("Player")
+
+ --Find the enemy with the highest priority
+ local maxpriority = -1
+ local maxprioritytarget = nil
+ for k,v in pairs(self.AwareEnemies) do
+ local priority = self:AttackPriority(v)
+ if(priority == nil) then
+ print("Nill priority hit after ")
+ PrintTable(self)
+ end
+ if(priority > maxpriority) then
+ maxpriority = priority
+ maxprioritytarget = v
+ end
+ end
+ self.Target = maxprioritytarget
+
+ --If we can't find anyone to attack, just stay idle
+ if(self.Target == nil) then
+ --print("Couldn't find anyone to attack!")
+ --Play an idle sequence
+ local randanim = math.Round(math.Rand(0,#self.IdleSequences))
+ self:PlaySequenceAndWait( self.IdleSequences[randanim] )
+ self:StartActivity( ACT_IDLE )
+ --print("Acting idle")
+ --If there's noone within 4000 units, just remove ourselves to save server resources
+ local closest = 5000
+ for k,v in pairs(player.GetAll()) do
+ local thisdist = self:GetPos():Distance(v:GetPos())
+ if(thisdist < closest) then
+ closest = thisdist
+ end
+ end
+ if(closest > 4000) then
+ print("Closes player is " .. closest .. " removeing self...")
+ self:BecomeRagdoll(DamageInfo())
+ end
+ else
+ --We have a target to attack!
+
+ --Find which attack will do the most dammage
+ local maxdammage = -1
+ local maxdammagefunc = nil
+ for k,v in pairs(self.Attacks) do
+ local dammagefunc = nil
+ local attackfunc = nil
+ for i,j in pairs(v) do
+ dammagefunc = i
+ attackfunc = j
+ end
+ local dammage = dammagefunc(self, self.Target)
+ if(dammage > maxdammage) then
+ maxdammage = dammage
+ maxdammagefunc = attackfunc
+ end
+ end
+
+ --Do that attack
+ if(maxdammagefunc) then
+ maxdammagefunc(self, self.Target)
+ end
+ end
+ coroutine.yield()
+ end
+
+ coroutine.yield()
+end
+]]
+
+function ENT:BehaveAct()
+ if(self.Act) then
+ self:Act()
+ else
+ print("NPC spawned without an Act function, this might be an error!")
+ end
+end
+
+function ENT:Use()
+
+end
+
+function ENT:BehaveUpdate(num)
+ --print(num)
+ --self:BehaveUpdate(num)
+
+ if(self.BehaveUpdate) then
+ self:BehaveUpdate(num)
+ end
+
+end
+
+function ENT:RunBehaviour()
+ if(self.Behave) then
+ self:Behave()
+ else
+ self:DefaultBehaviour()
+ end
+end
diff --git a/entities/weapons/hands.lua b/entities/weapons/hands.lua
new file mode 100644
index 0000000..3d74aa3
--- /dev/null
+++ b/entities/weapons/hands.lua
@@ -0,0 +1,142 @@
+AddCSLuaFile("hands.lua")
+
+SWEP.ViewModel = ""--"models/error.mdl"
+SWEP.WorldModel = ""--"models/error.mdl"
+
+SWEP.HoldType = "normal"
+
+SWEP.Primary.ClipSize = -1
+SWEP.Primary.DefaultClip = -1
+SWEP.Primary.Automatic = true
+SWEP.Primary.Ammo = "none"
+
+SWEP.Secondary.Clipsize = -1
+SWEP.Secondary.DefaultClip = -1
+SWEP.Secondary.Automatic = false
+SWEP.Secondary.Ammo = "none"
+
+SWEP.DrawAmmo = false
+SWEP.DrawCrosshair = false
+
+function SWEP:Initialize()
+ self:SetWeaponHoldType(self.HoldType)
+ self:DrawShadow(false)
+ self:SetNoDraw(true)
+
+ --[[
+ if (CLIENT) then
+ self.MOB = ClientsideModel("error.mdl")
+ self.MOB:SetNoDraw(true)
+ self.MOB:DrawShadow(false)
+ end
+ ]]
+end
+
+function SWEP:ShouldDropOnDie()
+ return false
+end
+
+function SWEP:Think()
+end
+
+function SWEP:Reload()
+end
+
+local Box = Vector(8,8,8)
+
+function SWEP:PrimaryAttack()
+ local rightitem = self.Owner.Inventory.Equiped["Left"]
+ if rightitem ~= false and rightitem.onClick ~= nil then
+ rightitem:onClick(self.Owner)
+ end
+ --[[
+ if (CLIENT and !IsFirstTimePredicted()) then return end
+ if (!self.Owner.Weapons or !self.Owner.Weapons[self.Owner.Select]) then return end
+ if (self.Owner.CD and self.Owner.CD > CurTime()) then return end
+
+ local item = self.Owner.Weapons[self.Owner.Select].Item
+
+ if (!item or !item.OnPrimary) then return end
+
+ self.Owner:SetAnimation( PLAYER_ATTACK1 )
+
+ local Trace = {
+ start = self.Owner:GetShootPos(),
+ endpos = self.Owner:GetShootPos()+self.Owner:GetAimVector()*item.Range,
+ filter = self.Owner,
+ mins = Box*-1,
+ maxs = Box,
+ }
+
+ local Tr = util.TraceHull(Trace)
+
+ item:OnPrimary(self.Owner,Tr)
+
+ self.Owner.CD = CurTime()+item.CD
+ ]]
+end
+
+function SWEP:SecondaryAttack()
+ --[[
+ if (CLIENT and !IsFirstTimePredicted()) then return end
+ if (!self.Owner.Weapons or !self.Owner.Weapons[self.Owner.Select]) then return end
+ if (self.Owner.CD and self.Owner.CD > CurTime()) then return end
+
+ local item = self.Owner.Weapons[self.Owner.Select].Item
+
+ if (!item or !item.OnSecondary) then return end
+
+ self.Owner:SetAnimation( PLAYER_ATTACK1 )
+
+ local Trace = {
+ start = self.Owner:GetShootPos(),
+ endpos = self.Owner:GetShootPos()+self.Owner:GetAimVector()*item.Range,
+ filter = self.Owner,
+ mins = Box*-1,
+ maxs = Box,
+ }
+
+ local Tr = util.TraceHull(Trace)
+
+ item:OnSecondary(self.Owner,Tr)
+
+ self.Owner.CD = CurTime()+item.CD
+ ]]
+end
+
+if (CLIENT) then
+ local Zero = Vector(1,1,1)
+ --[[
+ function SWEP:DrawWorldModel()
+ if (!self.Owner.Weapons or !self.Owner.Weapons[self.Owner.Select]) then return end
+
+ local item = self.Owner.Weapons[self.Owner.Select].Item
+
+ for k,v in pairs(item.Structure) do
+ local ID = self.Owner:LookupBone(v.Bone)
+ local Pos,Ang = self.Owner:GetBonePosition(ID)
+
+ local Offset = v.Pos*1
+ Offset:Rotate(Ang)
+ Pos = Pos + Offset
+
+ local Dang = Ang*1
+
+ Ang:RotateAroundAxis(Dang:Right(),v.Ang.p)
+ Ang:RotateAroundAxis(Dang:Up(),v.Ang.y)
+ Ang:RotateAroundAxis(Dang:Forward(),v.Ang.r)
+
+ self.MOB:SetModel(v.Model)
+ self.MOB:SetRenderOrigin(Pos)
+ self.MOB:SetRenderAngles(Ang)
+
+ local mat = Matrix()
+ mat:Scale( v.Size or Zero )
+
+ self.MOB:EnableMatrix( "RenderMultiply", mat )
+ self.MOB:SetupBones()
+ self.MOB:DrawModel()
+ end
+ end
+ ]]
+end
diff --git a/gamemode/autolua.lua b/gamemode/autolua.lua
new file mode 100644
index 0000000..3f7d07a
--- /dev/null
+++ b/gamemode/autolua.lua
@@ -0,0 +1,44 @@
+--[[
+ A few functions to make it easier to include files and folders
+]]
+local auto = {}
+
+local function ExecuteOnFolder(dir, recursive, func)
+ local path = GM.Folder:gsub("gamemodes/","") .. "/gamemode/"
+ local fpath = table.concat({path,dir,"/*"})
+ local files, directories = file.Find(fpath,"LUA")
+ for k,v in pairs(files) do
+ if string.GetExtensionFromFilename(v) ~= "lua" then continue end
+ local callpath = table.concat({path,dir,"/",v})
+ func(callpath)
+ end
+ if recursive then
+ for k,v in pairs(directories) do
+ local npath = table.concat({dir,"/",v})
+ ExecuteOnFolder(npath,true,func)
+ end
+ end
+end
+
+auto.AddLuaCSFolder = function(dir,recursive)
+ ExecuteOnFolder(dir,recursive,function(f)
+ if SERVER then AddCSLuaFile(f)
+ else include(f) end
+ end)
+end
+
+auto.AddLuaSVFolder = function(dir,recursive)
+ if CLIENT then return end
+ ExecuteOnFolder(dir,recursive,function(f)
+ include(f)
+ end)
+end
+
+auto.AddLuaSHFolder = function(dir,recursive)
+ ExecuteOnFolder(dir,recursive,function(f)
+ if SERVER then AddCSLuaFile(f) end
+ include(f)
+ end)
+end
+
+return auto
diff --git a/gamemode/cl_init.lua b/gamemode/cl_init.lua
new file mode 100644
index 0000000..6b5d18a
--- /dev/null
+++ b/gamemode/cl_init.lua
@@ -0,0 +1 @@
+include( "shared.lua" )
diff --git a/gamemode/client/cl_inventory.lua b/gamemode/client/cl_inventory.lua
new file mode 100644
index 0000000..6db72dd
--- /dev/null
+++ b/gamemode/client/cl_inventory.lua
@@ -0,0 +1,199 @@
+--[[
+ Displays the inventory, for more information see /gamemode/shared/inventory.lua
+]]
+print("Hello from cl_inventory.lua")
+local invfuncs = include("../shared/inventory_common.lua")
+local plyisininventory = false
+
+function ShowInventory(ply,cmd,args)
+ if plyisininventory then return end
+ plyisininventory = true
+ local width = ScrW()
+ local height = ScrH()
+ local dat = {}
+ dat.panel = vgui.Create( "DFrame" )
+ dat.redraw = ShowInventory
+ table.insert(LocalPlayer().invdisplays,dat)
+ local invpanel = dat.panel
+ invpanel:SetPos( 0, 0 )
+ invpanel:SetSize( width / 4, height )
+ invpanel:SetTitle( "Inventory" )
+ invpanel:SetDraggable( true )
+ invpanel:MakePopup()
+ invpanel.OnClose = function(self)
+ plyisininventory = false
+ end
+
+ local sheet = vgui.Create( "DPropertySheet", invpanel )
+ sheet:Dock( FILL )
+
+ local invsheet = vgui.Create( "DPanel", sheet )
+ invsheet.Paint = function( self, w, h ) draw.RoundedBox( 4, 0, 0, w, h, Color( 157, 160, 167 ) ) end
+ sheet:AddSheet( "Inventory", invsheet, "icon16/cross.png" )
+
+ local skillsheet = vgui.Create( "DPanel", sheet )
+ skillsheet.Paint = function( self, w, h ) draw.RoundedBox( 4, 0, 0, w, h, Color( 157, 160, 167 ) ) end
+ sheet:AddSheet( "Skills", skillsheet, "icon16/tick.png" )
+
+ --Display gear
+ local slotsize = math.Round(width / 32)
+ local displaypos = {
+ ["Head"] = {(width / 8) - slotsize, 25},
+ ["Body"] = {(width / 8) - slotsize, slotsize + 26},
+ ["Legs"] = {(width / 8) - slotsize, (slotsize * 2) + 27},
+ ["Boots"] = {(width / 8) - slotsize, (slotsize * 3) + 28},
+ ["Gloves"] = {(width / 8) + (slotsize), (slotsize * 2) + 27},
+ ["Left"] = {(width / 8) - (1.5 * slotsize), (slotsize * 4) + 29},
+ ["Right"] = {(width / 8) - (0.5 * slotsize), (slotsize * 4) + 29}
+ }
+ print("Displaying inventory:")
+ PrintTable(LocalPlayer().Inventory.Equiped)
+ for k,v in pairs (LocalPlayer().Inventory.Equiped) do
+ if v == false then
+ local eqslot = vgui.Create( "DPanel", invsheet )
+ eqslot:SetSize( slotsize, slotsize )
+ eqslot:SetPos(displaypos[k][1],displaypos[k][2])
+ eqslot:Receiver( "Inventory", function( receiver, tableOfDroppedPanels, isDropped, menuIndex, mouseX, mouseY )
+ if not isDropped then return end
+ print("Attempting to equip")
+ local icon = tableOfDroppedPanels[1]
+ local item = icon.Item
+ PrintTable(item)
+ print("In",k)
+ if item.Equipable == k then
+ net.Start("equipitem")
+ net.WriteUInt(icon.backpacknum,16) -- Backpack number
+ local fromtbl = icon.invpos
+ net.WriteUInt(fromtbl[1],16) -- From position
+ net.WriteUInt(fromtbl[2],16)
+ print("Writing string",k)
+ net.WriteString(k)
+ net.SendToServer()
+ end
+ end, {} )
+ else
+ print("eqslot",k,"was not false, it was")
+ PrintTable(v)
+ local eqslot = vgui.Create("DPanel",invsheet)
+ eqslot:SetSize(slotsize,slotsize)
+ eqslot:SetPos(displaypos[k][1],displaypos[k][2])
+ --eqslot:SetImage( "overviews/de_inferno", "vgui/avatar_default" )
+ --eqslot.Paint = function(self, w, h) draw.RoundedBox(4, 0,0,w,h,Color(100,0,0)) end
+ eqslot:Droppable("Inventory")
+ eqslot.Item = v
+ eqslot.wasequiped = k
+ end
+ end
+
+ local backpacksheet = vgui.Create( "DPropertySheet", invsheet )
+ backpacksheet:SetPos(0,slotsize * 6)
+ backpacksheet:SetSize((width / 4) - 25, height - (slotsize * 6) - 50)
+
+ for k,v in pairs(LocalPlayer().Inventory.Backpacks) do
+ local tbacksheet = vgui.Create( "DPanel", backpacksheet )
+ tbacksheet.Paint = function( self, w, h ) draw.RoundedBox( 4, 0, 0, w, h, Color( 157, 160, 167 ) ) end
+ backpacksheet:AddSheet( v[3], tbacksheet, "icon16/cross.png" )
+
+ invfuncs.DrawBackpackOnDPanel(tbacksheet,v,k,LocalPlayer())
+
+ --[[
+ local backgrid = vgui.Create( "DGrid", tbacksheet )
+ backgrid:SetPos( 10, 30 )
+ backgrid:SetCols( v[2][1] )
+ backgrid:SetColWide( v[2][2] )
+ backgrid:Dock(FILL)
+
+ for i=1,#(v[1]) do
+ for j=1,#(v[1][i]) do
+ if type(v[1][j][i]) == "table" then
+ print("Loading icon")
+ local item = v[1][j][i]
+ print("Item is:")
+ PrintTable(item)
+ local itemwidth = 0
+ for _,l in pairs(item.Shape) do
+ itemwidth = math.Max(itemwidth,#l)
+ end
+ local itemheight = #item.Shape
+ local invicon = vgui.Create( "DButton", tbacksheet )
+ invicon:SetSize(slotsize*itemwidth,slotsize*itemheight)
+ invicon:SetPos(slotsize*(i-1),slotsize*(j-1))
+ --invicon.Paint = function(self, w, h) draw.RoundedBox(4, 0,0,w,h,Color(0,100,0)) end
+ invicon.Item = item
+ invicon.invpos = {j,i}
+ invicon.backpack = k
+ invicon:Droppable("Inventory")
+ elseif not v[1][j][i] then
+ local emptyslot = vgui.Create("DPanel", tbacksheet)
+ emptyslot:SetSize(slotsize,slotsize)
+ emptyslot:SetPos(slotsize*(i-1),slotsize*(j-1))
+ --emptyslot.Paint = function(self, w, h) draw.RoundedBox(4, 0,0,w,h,Color(0,0,100)) end
+ emptyslot:Receiver( "Inventory", function( receiver, tableOfDroppedPanels, isDropped, menuIndex, mouseX, mouseY )
+ if not isDropped then return end
+ print("receiver",receiver)
+ print("menuIndex",menuIndex)
+ print("tableOfDroppedPanels",tableOfDroppedPanels)
+ PrintTable(tableOfDroppedPanels)
+ local item = tableOfDroppedPanels[1].Item
+ print("Checking if item:")
+ PrintTable(item)
+ print("Can fit in pack:",j,i)
+ if invfuncs.CanFitInBackpack(v,j,i,item) then
+ local fromtbl = tableOfDroppedPanels[1].invpos
+ local wasequiped = tableOfDroppedPanels[1].wasequiped
+ if wasequiped then
+ print("wasequiped",wasequiped)
+ net.Start("unequipitem")
+ net.WriteString(wasequiped)
+ net.WriteUInt(k,16)
+ net.WriteUInt(i,16)
+ net.WriteUInt(j,16)
+ net.SendToServer()
+ else
+ net.Start("moveitem")
+ net.WriteUInt(k,16) -- Backpack number
+ net.WriteUInt(fromtbl[1],16) -- From position
+ net.WriteUInt(fromtbl[2],16)
+ net.WriteUInt(j,16) -- To position
+ net.WriteUInt(i,16)
+ net.SendToServer()
+ if item.onEquip ~= nil then
+ item:onEquip(LocalPlayer())
+ end
+ end
+ end
+ end, {} )
+ end
+ end
+ end
+ ]]
+ end
+
+end
+
+hook.Add("OnSpawnMenuOpen","ArteryOpenInventory",ShowInventory)
+hook.Add("OnSpawnMenuClose","ArteryCloseInventory",function()
+ if LocalPlayer().invpanel == nil then return end
+ LocalPlayer().invpanel:Remove()
+ plyisininventory = false
+end)
+
+concommand.Add("showinventory",ShowInventory)
+local viewdistance = 100
+local rotatespeed = 65
+hook.Add("CalcView","ArteryInventoryView",function(ply,pos,ang,fov,nearz,farz)
+ local view = {}
+ view.origin = pos
+ if plyisininventory then
+ local xoff = viewdistance * math.sin(math.rad(CurTime() * rotatespeed))
+ local yoff = viewdistance * math.cos(math.rad(CurTime() * rotatespeed))
+ view.origin = view.origin + ( Vector(xoff,yoff,10) )
+ ang.pitch = 20
+ ang.yaw = (-CurTime() * rotatespeed) - 90
+ end
+ view.angles = ang
+ view.fov = fov
+ view.drawviewer = plyisininventory
+
+ return view
+end)
diff --git a/gamemode/client/cl_pac.lua b/gamemode/client/cl_pac.lua
new file mode 100644
index 0000000..6a7abed
--- /dev/null
+++ b/gamemode/client/cl_pac.lua
@@ -0,0 +1,2 @@
+
+local pmeta = FindMetaTable("Player")
diff --git a/gamemode/client/cl_systems.lua b/gamemode/client/cl_systems.lua
new file mode 100644
index 0000000..0165239
--- /dev/null
+++ b/gamemode/client/cl_systems.lua
@@ -0,0 +1,4 @@
+--[[
+ Something to display all the systems delt with serverside
+]]
+local systems = {}
diff --git a/gamemode/client/vgui/vgui_DMultiModelPanel.lua b/gamemode/client/vgui/vgui_DMultiModelPanel.lua
new file mode 100644
index 0000000..37d0883
--- /dev/null
+++ b/gamemode/client/vgui/vgui_DMultiModelPanel.lua
@@ -0,0 +1,161 @@
+local PANEL = {}
+
+AccessorFunc( PANEL, "m_fAnimSpeed", "AnimSpeed" )
+AccessorFunc( PANEL, "vCamPos", "CamPos" )
+AccessorFunc( PANEL, "fFOV", "FOV" )
+AccessorFunc( PANEL, "vLookatPos", "LookAt" )
+AccessorFunc( PANEL, "aLookAngle", "LookAng" )
+AccessorFunc( PANEL, "colAmbientLight", "AmbientLight" )
+AccessorFunc( PANEL, "colColor", "Color" )
+AccessorFunc( PANEL, "bAnimated", "Animated" )
+
+function PANEL:Init()
+
+ self.Entities = {}
+ self.LastPaint = 0
+ self.DirectionalLight = {}
+ self.FarZ = 4096
+
+ self:SetCamPos( Vector( 50, 50, 50 ) )
+ self:SetLookAt( Vector( 0, 0, 40 ) )
+ self:SetFOV( 70 )
+
+ self:SetText( "" )
+ self:SetAnimSpeed( 0.5 )
+ self:SetAnimated( false )
+
+ self:SetAmbientLight( Color( 50, 50, 50 ) )
+
+ self:SetDirectionalLight( BOX_TOP, Color( 255, 255, 255 ) )
+ self:SetDirectionalLight( BOX_FRONT, Color( 255, 255, 255 ) )
+
+ self:SetColor( Color( 255, 255, 255, 255 ) )
+
+end
+
+function PANEL:SetDirectionalLight( iDirection, color )
+ self.DirectionalLight[ iDirection ] = color
+end
+
+function PANEL:AddModel( strModelName )
+
+ -- Note: Not in menu dll
+ if ( !ClientsideModel ) then return end
+
+ self.Entities[#self.Entities+1] = ClientsideModel(strModelName, RENDER_GROUP_OPAQUE_ENTITY)
+ if ( !IsValid( self.Entities[#self.Entities] ) ) then return end
+
+ self.Entities[#self.Entities]:SetNoDraw( true )
+ self.Entities[#self.Entities]:SetIK( false )
+
+end
+
+function PANEL:DrawModel()
+
+ local curparent = self
+ local rightx = self:GetWide()
+ local leftx = 0
+ local topy = 0
+ local bottomy = self:GetTall()
+ local previous = curparent
+ while( curparent:GetParent() != nil ) do
+ curparent = curparent:GetParent()
+ local x, y = previous:GetPos()
+ topy = math.Max( y, topy + y )
+ leftx = math.Max( x, leftx + x )
+ bottomy = math.Min( y + previous:GetTall(), bottomy + y )
+ rightx = math.Min( x + previous:GetWide(), rightx + x )
+ previous = curparent
+ end
+ render.SetScissorRect( leftx, topy, rightx, bottomy, true )
+
+ for k,v in pairs(self.Entities) do
+ local ret = self:PreDrawModel( v )
+ if ( ret != false ) then
+ v:DrawModel()
+ self:PostDrawModel( v )
+ end
+ end
+
+ render.SetScissorRect( 0, 0, 0, 0, false )
+
+end
+
+function PANEL:PreDrawModel( ent )
+ return true
+end
+
+function PANEL:PostDrawModel( ent )
+
+end
+
+function PANEL:Paint( w, h )
+ for k,v in pairs(self.Entities) do
+ if ( !IsValid( v ) ) then continue end
+
+ local x, y = self:LocalToScreen( 0, 0 )
+
+ self:LayoutEntity( v )
+
+ local ang = self.aLookAngle
+ if ( !ang ) then
+ ang = ( self.vLookatPos - self.vCamPos ):Angle()
+ end
+
+ cam.Start3D( self.vCamPos, ang, self.fFOV, x, y, w, h, 5, self.FarZ )
+
+ render.SuppressEngineLighting( true )
+ render.SetLightingOrigin( v:GetPos() )
+ render.ResetModelLighting( self.colAmbientLight.r / 255, self.colAmbientLight.g / 255, self.colAmbientLight.b / 255 )
+ render.SetColorModulation( self.colColor.r / 255, self.colColor.g / 255, self.colColor.b / 255 )
+ render.SetBlend( ( self:GetAlpha() / 255 ) * ( self.colColor.a / 255 ) )
+
+ for i = 0, 6 do
+ local col = self.DirectionalLight[ i ]
+ if ( col ) then
+ render.SetModelLighting( i, col.r / 255, col.g / 255, col.b / 255 )
+ end
+ end
+
+ self:DrawModel()
+
+ render.SuppressEngineLighting( false )
+ cam.End3D()
+
+ self.LastPaint = RealTime()
+ end
+end
+
+--[[
+function PANEL:StartScene( name )
+
+ if ( IsValid( self.Scene ) ) then
+ self.Scene:Remove()
+ end
+
+ self.Scene = ClientsideScene( name, self.Entity )
+
+end
+]]
+
+function PANEL:LayoutEntity( Entity )
+
+ --
+ -- This function is to be overriden
+ --
+
+ if ( self.bAnimated ) then
+ self:RunAnimation()
+ end
+ Entity:SetAngles( Angle( 0, RealTime() * 10 % 360, 0 ) )
+
+end
+
+function PANEL:OnRemove()
+ for k,v in pairs(self.Entities) do
+ v:Remove()
+ self.Entities[k] = nil
+ end
+end
+
+derma.DefineControl( "DModelPanel", "A panel containing a model", PANEL, "DModelPanel" )
diff --git a/gamemode/init.lua b/gamemode/init.lua
new file mode 100644
index 0000000..0429d01
--- /dev/null
+++ b/gamemode/init.lua
@@ -0,0 +1,5 @@
+AddCSLuaFile( "autolua.lua" )
+AddCSLuaFile( "cl_init.lua" )
+AddCSLuaFile( "shared.lua" )
+
+include( "shared.lua" )
diff --git a/gamemode/server/heatmap.lua b/gamemode/server/heatmap.lua
new file mode 100644
index 0000000..7beb30f
--- /dev/null
+++ b/gamemode/server/heatmap.lua
@@ -0,0 +1,141 @@
+--[[
+ Some helper methods for useing heatmaps
+]]
+
+print("Hello from heatmap.lua!")
+local prs = pairs
+local iprs = ipairs
+local prnt = print
+local tblins,tbldel = table.insert, table.remove
+local pow,sqrt,max = math.pow, math.sqrt, math.max
+
+heatmap = {}
+
+local function VectorDistance(vec1,vec2)
+ if vec1.Distance then return vec1:Distance(vec2)
+ else
+ local dist = 0
+ for k,v in prs(vec1) do
+ local add = pow(vec1[k]-vec2[k],2)
+ dist = dist + add
+ end
+ dist = sqrt(dist)
+ return dist
+ end
+end
+
+local function VectorLength(vec)
+ if vec.Length then return vec:Length()
+ else
+ local len = 0
+ for k,v in prs do
+ local add = pow(v,2)
+ len = len + add
+ end
+ len = sqrt(len)
+ return len
+ end
+end
+
+
+local function RegisterEffect(self, func, position)
+ local stbl = {position,func}
+ tblins(self.heatpoints,#self.heatpoints+1,stbl)
+end
+
+local function CalculateFor(self, position)
+ local sh = self.heatpoints[1]
+ local total = sh[2](sh[1]-position,self.curtime)
+ for k=2,#self.heatpoints do
+ sh = self.heatpoints[k]
+ total, shouldremove = total + sh[2](sh[1]-position,self.curtime)
+ if(shouldremove) then tbldel(k) end
+ end
+ return total
+end
+
+--- Creates a heat map to keep track of effects.
+-- Effects must be structured as a function that takes a vector (position from origin of effect) and number(time) and returns a value
+-- @return a heatmap object
+function heatmap.CreateHeatMap()
+ local tbl = {}
+ tbl.heatpoints = {}
+ tbl.curtime = 0
+ tbl.RegisterEffect = RegisterEffect
+ tbl.CalculateFor = CalculateFor
+ return tbl
+end
+
+function heatmap.UniformInfiniteForever(field)
+ return function(vector, time)
+ return field, false
+ end
+end
+
+function heatmap.UniformInfiniteLinearDecay(field,decayrate)
+ return function(vector,time)
+ return heatmap.UniformInfiniteForever(field)-(time*decayrate), false
+ end
+end
+
+function heatmap.UniformInfiniteLinearDecayGrounded(field,decayrate)
+ local removetime = field/decayrate
+ return function(vector,time)
+ return max(heatmap.UniformInfiniteLinearDecay(field,decayrate),0), time < removetime
+ end
+end
+
+function heatmap.LinearInfiniteForever(field)
+ return function(vector, time)
+ return field - VectorLength(vector), false
+ end
+end
+
+function heatmap.LinearInfiniteForeverGrounded(field)
+ return function(vector,time)
+ return max(heatmap.LinearInfiniteForever(field),0), false
+ end
+end
+
+function heatmap.LinearInfiniteLinearDecay(field,decayrate)
+ return function(vector, time)
+ return field - VectorLength(vector) - (time*decayrate), false
+ end
+end
+
+function heatmap.LinearInfiniteLinearDecayGrounded(field,decayrate)
+ local removetime = field/decayrate
+ return function(vector, time)
+ return max(field-VectorLength(vector) - (time*decayrate),0), time < removetime
+ end
+end
+
+function heatmap.ParabolicInfiniteForever(field, power)
+ return function(vector, time)
+ return field - pow(VectorLength(vector),power)/pow(100,power), false
+ end
+end
+
+function heatmap.ParabolicInfiniteForeverGrounded(field, power)
+ return function(vector, time)
+ local pre = heatmap.ParabolicInfiniteForever(field, power)
+ --print("pre is:")
+ --print(pre)
+ return max(pre,0), false
+ end
+end
+
+function heatmap.ParabolicInfiniteLinearDecay(field,power,decayrate)
+ return function(vector, time)
+ return heatmap.ParabolicInfiniteForever(field, power) - (time*decayrate), false
+ end
+end
+
+function heatmap.ParabolicInfiniteLinearDecayGrounded(field,power,decayrate)
+ local removetime = field/decayrate
+ return function(vector,time)
+ return max(heatmap.ParabolicInfiniteLinearDecay(field,power,decayrate),0), time < removetime
+ end
+end
+
+return heatmap
diff --git a/gamemode/server/sv_config.lua b/gamemode/server/sv_config.lua
new file mode 100644
index 0000000..e4d43ab
--- /dev/null
+++ b/gamemode/server/sv_config.lua
@@ -0,0 +1,19 @@
+--[[
+ Some things that I might want to configure
+]]
+
+ART.defaults = {}
+ART.defaults.starting_inventory = '{"Backpacks":[[[[false,false,false,false,false],[false,false,false,false,false],[false,false,false,false,false],[false,false,false,false,false],[false,false,false,false,false]],[5,5],"Rucksack"]],"Equiped":{"Gloves":false,"Left":false,"Head":false,"Legs":false,"Right":false,"Body":false,"Boots":false}}'
+
+ART.defaults.starting_position = "185.690247 310.664398 515.031250"
+ART.defaults.starting_world = "0.0.0.0:0"
+ART.config = {}
+ART.config.server_world = game.GetIPAddress()
+
+local mysqlconfig = file.Read("artery/mysql.txt")
+for _,line in pairs(string.Explode("\n",mysqlconfig,false)) do
+ print(line)
+ local key, value = unpack(string.Explode("=",line,false))
+ print("setting",key,"to",value)
+ ART.config[key] = value
+end
diff --git a/gamemode/server/sv_database.lua b/gamemode/server/sv_database.lua
new file mode 100644
index 0000000..59b685f
--- /dev/null
+++ b/gamemode/server/sv_database.lua
@@ -0,0 +1,155 @@
+--One-type setup stuff
+print("Hello from database.lua!!")
+require("mysqloo")
+
+local createplayerquery
+local createplayerprepare = [[
+INSERT INTO playerdata (`SteamID`, `PlayerName`,`Inventory`,`WorldPosition`,`World`) VALUES(?, ?, ?, ?, ?)]]
+local createtablequery = [[
+create table if not exists playerdata(SteamID text, PlayerName text, Inventory json, WorldPosition text, World text)]]
+
+local function connectToDatabase()
+ if ART.database ~= nil then return end
+ ART.database = mysqloo.connect(
+ ART.config.dbhost,
+ ART.config.dbuser,
+ ART.config.dbpass,
+ ART.config.dbname,
+ ART.config.dbport
+ )
+ local db = ART.database
+
+ function db:onConnected()
+ print("Database connected successfully")
+ local q = self:query("SELECT 5+5")
+ function q:onSuccess(data)
+ print("Query successful")
+ PrintTable(data)
+ end
+ function q:onError(err, sql)
+ print("Query errored!")
+ print("Query",sql)
+ error(err)
+ end
+ q:start()
+ end
+
+ function db:onConnectionFailed( err )
+ print( "Connection to database failed!" )
+ print( "Error:",err )
+ end
+ print("Connecting to db")
+ db:connect()
+end
+
+connectToDatabase()
+
+local function checkDatabase()
+ local db = ART.database
+ print("Checking if playerdata table exists")
+ local q = db:query(createtablequery)
+ function q:onSuccess(data)
+ print("Got data:")
+ PrintTable(data)
+ end
+ function q:onError(err,sql)
+ print("Query error:")
+ print("Query",sql)
+ print("Error",err)
+ end
+ q:start()
+ print("Tried to query, something should be printed soon!")
+end
+
+checkDatabase()
+
+local function loadQueries()
+ local db = ART.database
+ print("Loading queries")
+ createplayerquery = db:prepare(createplayerprepare)
+ print("starting inventory:")
+ print(ART.defaults.starting_inventory)
+ createplayerquery:setString(3,ART.defaults.starting_inventory)
+ createplayerquery:setString(4,ART.defaults.starting_position)
+ createplayerquery:setString(5,ART.defaults.starting_world)
+ function createplayerquery:onSuccess(data)
+ print("Created player entry successfully!")
+ end
+ function createplayerquery:onError(err)
+ print("An error occured while createing a player entry: " .. err)
+ end
+ ART.DatabaseConnected = true
+end
+
+loadQueries()
+
+function ART.loadPlayerData(ply)
+ assert(ART.DatabaseConnected,"Player joined while setup was not complete!")
+ print("Attempting to load player data")
+ local steamid = ply:SteamID()
+ local db = ART.database
+ local q = db:query([[
+select Inventory, WorldPosition, World from playerdata where SteamID="]] .. steamid .. "\"")
+ function q:onSuccess(data)
+ if #data == 0 then --Player does not have an entry, make one!
+ print("Player does not have entry!")
+ if ART.config.server_world ~= ART.defaults.starting_world then
+ print("You didn't connect to the starting world, you are on:")
+ print(ART.config.server_world)
+ print("The starting world is")
+ print(ART.defaults.starting_world)
+ local ccmd = "connect " .. ART.defaults.starting_world
+ print("Running concommand:" .. ccmd)
+ --ply:ConCommand(ccmd)
+ else
+ print("New player without entry in database, and he's connected to the right place!")
+ createplayerquery:setString(1,steamid)
+ createplayerquery:setString(2,ply:Nick())
+ createplayerquery:start()
+ ply:ConCommand("retry") -- reconnect to the server to load player data normally
+ end
+ else
+ assert(#data == 1, "Two players with the same steamID? Something's gone horribly wrong!")
+ print("Loaded player data,")
+ --PrintTable(data)
+ local world = data[1].World
+ local inv = data[1].Inventory
+ local worldpos = data[1].WorldPosition
+ print("World:" .. world)
+ PrintTable(data)
+ if world ~= ART.config.server_world then
+ print("Joined the wrong world, redirecting!")
+ print("You are on :" .. ART.config.server_world .. " which is not " .. world)
+ local ccmd = "connect " .. world
+ --ply:ConCommand(ccmd)
+ return
+ end
+ --Otherwise, we're in the right world, load our data
+ ply:LoadInventory(inv)
+ local postbl = string.Explode(" ", worldpos)
+ local posvec = Vector(postbl[1],postbl[2],postbl[3])
+ print("Setting player pos to:")
+ print(posvec)
+ ply:SetPos(posvec)
+ end
+
+ end
+ function q:onError(err,sql)
+ print("Query error:")
+ print("Query",sql)
+ print("Error",err)
+ end
+ q:start()
+end
+
+--A randomly assigned model based on a player's UniqueID, so it should always stay the same.
+
+--[[
+hook.Add("PlayerInitialSpawn","ArteryPlayerInit",function(ply)
+ local modelnum = ply:UniqueID() % (#models)
+ print("Setting player model")
+ ply:SetModel(models[modelnum])
+ print("Loading data")
+ ART.loadPlayerData(ply)
+end)
+]]
diff --git a/gamemode/server/sv_loadplayer.lua b/gamemode/server/sv_loadplayer.lua
new file mode 100644
index 0000000..397c6cb
--- /dev/null
+++ b/gamemode/server/sv_loadplayer.lua
@@ -0,0 +1,15 @@
+
+local models = {}
+for k=1,9 do
+ models[#models+1] = "models/player/Group01/male_0" .. k .. ".mdl"
+ models[#models+1] = "models/player/Group02/Male_0" .. k .. ".mdl"
+end
+
+hook.Add("PlayerInitialSpawn","ArteryPlayerLoad",function(pl)
+ local modelnum = pl:UniqueID() % (#models)
+ ART.loadPlayerData(pl)
+ pl:SetModel(models[modelnum])
+ --pl:Give("weapon_pistol")
+ pl:Give("hands")
+ pl:SelectWeapon("hands")
+end)
diff --git a/gamemode/server/sv_mapconfig.lua b/gamemode/server/sv_mapconfig.lua
new file mode 100644
index 0000000..67a20ae
--- /dev/null
+++ b/gamemode/server/sv_mapconfig.lua
@@ -0,0 +1,19 @@
+--Loads map config form a file
+
+local chests = file.Read("artery/maps/" .. game.GetMap() .. "/chests.txt")
+local npcs = file.Read("artery/maps/" .. game.GetMap() .. "/npcs.txt")
+
+if chests == nil then return end
+if npcs == nil then return end
+
+for _,line in pairs(string.Explode("\n",chests,false)) do
+ local chest = util.JSONToTable(line)
+ local chestent = ents.Create("art_chest")
+ for k,v in pairs(chest.data) do
+ chestent[k] = v
+ end
+ for k,v in pairs(chest.procedures) do
+ chestent[k](unpack(v))
+ end
+ chestent:Spawn()
+end
diff --git a/gamemode/server/sv_pac.lua b/gamemode/server/sv_pac.lua
new file mode 100644
index 0000000..27b2ed9
--- /dev/null
+++ b/gamemode/server/sv_pac.lua
@@ -0,0 +1,28 @@
+hook.Add("PrePACConfigApply", "donators only", function(ply, outfit_data)
+ if not ply:IsSuperAdmin() then
+ return false, "give us money!"
+ end
+end)
+
+hook.Add( "PrePACEditorOpen", "RestrictToSuperadmin", function( ply )
+ if not ply:IsSuperAdmin( ) then
+ return false
+ end
+end )
+
+util.AddNetworkString("requestpac")
+util.AddNetworkString("responsepac")
+
+--be able to stream pac data to clients on-demand
+net.Receive("requestpac",function(ln,ply)
+ local name = net.ReadString()
+ local pdata = file.Read(string.format("artery/pac/%s.txt",name)) --make sure to have the .txt, so dot-dot-slash attacks can't read the mysql file.
+ net.Start("responsepac")
+ net.WriteString(pdata)
+ net.Send(ply)
+end)
+
+hook.Add("PlayerInitialSpawn", "AllowPacThings",function(ply)
+ --pac.SetupENT(ply, false)
+ PrintTable(pac)
+end)
diff --git a/gamemode/server/sv_systems.lua b/gamemode/server/sv_systems.lua
new file mode 100644
index 0000000..ad1b901
--- /dev/null
+++ b/gamemode/server/sv_systems.lua
@@ -0,0 +1,21 @@
+--[[
+ Calculates various needs for the player, displayed in /gamemode/client/cl_systems.lua
+ Each need has a min and a max (ex health, stamina ect.)
+
+ Provides:
+ ART.RegisterSystem(string_name, table_system)
+ Registers the system with all players. Two systems may not share the same name.
+]]
+
+local pmeta = FindMetaTable("Player")
+
+pmeta.Systems = {}
+
+function ART.RegisterSystem(tbl)
+ assert(tbl.Name ~= nil,"Attempted to register a system with a nil name")
+ pmeta.Systems[name] = tbl
+end
+
+concommand.Add("DisplaySystems",function()
+ PrintTable(pmeta.Systems)
+end)
diff --git a/gamemode/server/systems/health.lua b/gamemode/server/systems/health.lua
new file mode 100644
index 0000000..7ead999
--- /dev/null
+++ b/gamemode/server/systems/health.lua
@@ -0,0 +1,12 @@
+
+local SYSTEM = {}
+
+SYSTEM.onthink = function(ply)
+
+end
+
+SYSTEM.ontakedamage = function(ply)
+
+end
+
+return SYSTEM
diff --git a/gamemode/server/test/testfile.lua b/gamemode/server/test/testfile.lua
new file mode 100644
index 0000000..95e40fa
--- /dev/null
+++ b/gamemode/server/test/testfile.lua
@@ -0,0 +1,48 @@
+--print("This is a test file to see if it gets included! Test!")
+--Msg("Testing heatmap.lua\n")
+local hm = heatmap.CreateHeatMap()
+--PrintTable(hm)
+--PrintTable(heatmap)
+--local effect = heatmap.UniformInfiniteForever(5)
+--hm:RegisterEffect(effect,Vector(0,0,0))
+--PrintTable(hm)
+--local neweffect = heatmap.LinearInfiniteForeverGrounded(2000,Vector(0,0,0))
+--hm:RegisterEffect(neweffect,Vector(0,0,0))
+--PrintTable(hm)
+local decayeffect =
+heatmap.LinearInfiniteLinearDecayGrounded(2000,5)
+hm:RegisterEffect(decayeffect,Vector(4000,4000,0))
+local bubbleeffect = heatmap.ParabolicInfiniteForeverGrounded(1000,2.5)
+hm:RegisterEffect(bubbleeffect,Vector(0,0,0))
+
+function sendHeatMap(ply)
+ local points = {}
+ net.Start("showheatmap")
+ for i=0,10000,100 do
+ points[i] = {}
+ for j=0,10000,100 do
+ local offset = --[[ply:GetPos() + ]]Vector(i,j,0) + Vector(-5000,-5000,0)
+ points[i][j] = hm:CalculateFor(offset, 0)
+ --net.WriteVector(offset)
+ net.WriteFloat(points[i][j])
+ --print("at ("..i..","..j..") is ")
+ --print(points[i][j])
+ end
+ end
+ net.Send(ply)
+end
+
+function callloop(ply)
+ sendHeatMap(ply)
+ hm.curtime = hm.curtime + 0.5
+ timer.Simple(0.5,function() callloop(ply) end)
+end
+
+util.AddNetworkString("showheatmap")
+concommand.Add("ShowHeatMap",function(ply,cmd,args)
+ callloop(ply)
+end)
+
+concommand.Add("HeatMapAt",function(ply,cmd,args)
+ print(hm:CalculateFor(ply:GetPos(),0))
+end)
diff --git a/gamemode/shared.lua b/gamemode/shared.lua
new file mode 100644
index 0000000..f829a45
--- /dev/null
+++ b/gamemode/shared.lua
@@ -0,0 +1,14 @@
+local a = include("autolua.lua")
+
+ART = {}
+
+a.AddLuaCSFolder("client",true)
+a.AddLuaSHFolder("shared",true)
+a.AddLuaSVFolder("server",false)
+
+GM.Name = "Artery"
+GM.Author = "Alexander \"Apickx\" Pickering"
+GM.Email = "apickx@cogarr.org"
+GM.Website = "cogarr.net"
+
+print("Hello from shared.lua!")
diff --git a/gamemode/shared/aes.lua b/gamemode/shared/aes.lua
new file mode 100644
index 0000000..5c4072a
--- /dev/null
+++ b/gamemode/shared/aes.lua
@@ -0,0 +1,526 @@
+print("Hello from aes.lua!")
+
+local Stream = include("lockbox/stream.lua");
+local Array = include("lockbox/array.lua");
+
+local Bit = include("lockbox/bit.lua");
+--local Math = require("math");
+
+
+local AND = bit.band;
+local OR = bit.bor;
+local NOT = bit.bnot;
+local XOR = bit.bxor;
+--local LROT = Bit.lrotate;
+--local RROT = Bit.rrotate;
+local LSHIFT = bit.lshift;
+local RSHIFT = bit.rshift;
+
+local SBOX = {
+ [0]=0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16};
+
+local ISBOX = {
+ [0]=0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D};
+
+local ROW_SHIFT = { 1, 6, 11, 16, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,};
+local IROW_SHIFT = { 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3, 16, 13, 10, 7, 4,};
+
+local ETABLE = {
+ [0]=0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, 0x96, 0xA1, 0xF8, 0x13, 0x35,
+ 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, 0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA,
+ 0xE5, 0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, 0x90, 0xAB, 0xE6, 0x31,
+ 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, 0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD,
+ 0x4C, 0xD4, 0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, 0x28, 0x78, 0x88,
+ 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, 0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A,
+ 0xB5, 0xC4, 0x57, 0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, 0x61, 0xA3,
+ 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, 0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0,
+ 0xFB, 0x16, 0x3A, 0x4E, 0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, 0x41,
+ 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, 0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75,
+ 0x9F, 0xBA, 0xD5, 0x64, 0xAC, 0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80,
+ 0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, 0xB1, 0xC8, 0x43, 0xC5, 0x54,
+ 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, 0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA,
+ 0x45, 0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, 0xC6, 0x51, 0xF3, 0x0E,
+ 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, 0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17,
+ 0x39, 0x4B, 0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, 0x52, 0xF6, 0x01};
+
+local LTABLE = {
+ [0]=0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1A, 0xC6, 0x4B, 0xC7, 0x1B, 0x68, 0x33, 0xEE, 0xDF, 0x03,
+ 0x64, 0x04, 0xE0, 0x0E, 0x34, 0x8D, 0x81, 0xEF, 0x4C, 0x71, 0x08, 0xC8, 0xF8, 0x69, 0x1C, 0xC1,
+ 0x7D, 0xC2, 0x1D, 0xB5, 0xF9, 0xB9, 0x27, 0x6A, 0x4D, 0xE4, 0xA6, 0x72, 0x9A, 0xC9, 0x09, 0x78,
+ 0x65, 0x2F, 0x8A, 0x05, 0x21, 0x0F, 0xE1, 0x24, 0x12, 0xF0, 0x82, 0x45, 0x35, 0x93, 0xDA, 0x8E,
+ 0x96, 0x8F, 0xDB, 0xBD, 0x36, 0xD0, 0xCE, 0x94, 0x13, 0x5C, 0xD2, 0xF1, 0x40, 0x46, 0x83, 0x38,
+ 0x66, 0xDD, 0xFD, 0x30, 0xBF, 0x06, 0x8B, 0x62, 0xB3, 0x25, 0xE2, 0x98, 0x22, 0x88, 0x91, 0x10,
+ 0x7E, 0x6E, 0x48, 0xC3, 0xA3, 0xB6, 0x1E, 0x42, 0x3A, 0x6B, 0x28, 0x54, 0xFA, 0x85, 0x3D, 0xBA,
+ 0x2B, 0x79, 0x0A, 0x15, 0x9B, 0x9F, 0x5E, 0xCA, 0x4E, 0xD4, 0xAC, 0xE5, 0xF3, 0x73, 0xA7, 0x57,
+ 0xAF, 0x58, 0xA8, 0x50, 0xF4, 0xEA, 0xD6, 0x74, 0x4F, 0xAE, 0xE9, 0xD5, 0xE7, 0xE6, 0xAD, 0xE8,
+ 0x2C, 0xD7, 0x75, 0x7A, 0xEB, 0x16, 0x0B, 0xF5, 0x59, 0xCB, 0x5F, 0xB0, 0x9C, 0xA9, 0x51, 0xA0,
+ 0x7F, 0x0C, 0xF6, 0x6F, 0x17, 0xC4, 0x49, 0xEC, 0xD8, 0x43, 0x1F, 0x2D, 0xA4, 0x76, 0x7B, 0xB7,
+ 0xCC, 0xBB, 0x3E, 0x5A, 0xFB, 0x60, 0xB1, 0x86, 0x3B, 0x52, 0xA1, 0x6C, 0xAA, 0x55, 0x29, 0x9D,
+ 0x97, 0xB2, 0x87, 0x90, 0x61, 0xBE, 0xDC, 0xFC, 0xBC, 0x95, 0xCF, 0xCD, 0x37, 0x3F, 0x5B, 0xD1,
+ 0x53, 0x39, 0x84, 0x3C, 0x41, 0xA2, 0x6D, 0x47, 0x14, 0x2A, 0x9E, 0x5D, 0x56, 0xF2, 0xD3, 0xAB,
+ 0x44, 0x11, 0x92, 0xD9, 0x23, 0x20, 0x2E, 0x89, 0xB4, 0x7C, 0xB8, 0x26, 0x77, 0x99, 0xE3, 0xA5,
+ 0x67, 0x4A, 0xED, 0xDE, 0xC5, 0x31, 0xFE, 0x18, 0x0D, 0x63, 0x8C, 0x80, 0xC0, 0xF7, 0x70, 0x07};
+
+local MIXTABLE = {
+ 0x02, 0x03, 0x01, 0x01,
+ 0x01, 0x02, 0x03, 0x01,
+ 0x01, 0x01, 0x02, 0x03,
+ 0x03, 0x01, 0x01, 0x02};
+
+local IMIXTABLE = {
+ 0x0E, 0x0B, 0x0D, 0x09,
+ 0x09, 0x0E, 0x0B, 0x0D,
+ 0x0D, 0x09, 0x0E, 0x0B,
+ 0x0B, 0x0D, 0x09, 0x0E};
+
+local RCON = {
+[0] = 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
+0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
+0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
+0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
+0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
+0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
+0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
+0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
+0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
+0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
+0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
+0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
+0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
+0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
+0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d};
+
+
+local GMUL = function(A,B)
+ if(A == 0x01) then return B; end
+ if(B == 0x01) then return A; end
+ if(A == 0x00) then return 0; end
+ if(B == 0x00) then return 0; end
+ print("Gettin gthe LTable of " .. A)
+ print("Getting the LTable of " .. B)
+ local LA = LTABLE[A];
+ local LB = LTABLE[B];
+
+ local sum = LA + LB;
+ if (sum > 0xFF) then sum = sum - 0xFF; end
+
+ return ETABLE[sum];
+end
+
+local byteSub = Array.substitute;
+
+local shiftRow = Array.permute;
+
+local mixCol = function(i,mix)
+ local out = {};
+
+ local a,b,c,d;
+ print("I is:")
+ PrintTable(i)
+ a = GMUL(i[ 1],mix[ 1]);
+ b = GMUL(i[ 2],mix[ 2]);
+ c = GMUL(i[ 3],mix[ 3]);
+ d = GMUL(i[ 4],mix[ 4]);
+ out[ 1] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[ 1],mix[ 5]);
+ b = GMUL(i[ 2],mix[ 6]);
+ c = GMUL(i[ 3],mix[ 7]);
+ d = GMUL(i[ 4],mix[ 8]);
+ out[ 2] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[ 1],mix[ 9]);
+ b = GMUL(i[ 2],mix[10]);
+ c = GMUL(i[ 3],mix[11]);
+ d = GMUL(i[ 4],mix[12]);
+ out[ 3] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[ 1],mix[13]);
+ b = GMUL(i[ 2],mix[14]);
+ c = GMUL(i[ 3],mix[15]);
+ d = GMUL(i[ 4],mix[16]);
+ out[ 4] = XOR(XOR(a,b),XOR(c,d));
+
+
+ a = GMUL(i[ 5],mix[ 1]);
+ b = GMUL(i[ 6],mix[ 2]);
+ c = GMUL(i[ 7],mix[ 3]);
+ d = GMUL(i[ 8],mix[ 4]);
+ out[ 5] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[ 5],mix[ 5]);
+ b = GMUL(i[ 6],mix[ 6]);
+ c = GMUL(i[ 7],mix[ 7]);
+ d = GMUL(i[ 8],mix[ 8]);
+ out[ 6] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[ 5],mix[ 9]);
+ b = GMUL(i[ 6],mix[10]);
+ c = GMUL(i[ 7],mix[11]);
+ d = GMUL(i[ 8],mix[12]);
+ out[ 7] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[ 5],mix[13]);
+ b = GMUL(i[ 6],mix[14]);
+ c = GMUL(i[ 7],mix[15]);
+ d = GMUL(i[ 8],mix[16]);
+ out[ 8] = XOR(XOR(a,b),XOR(c,d));
+
+
+ a = GMUL(i[ 9],mix[ 1]);
+ b = GMUL(i[10],mix[ 2]);
+ c = GMUL(i[11],mix[ 3]);
+ d = GMUL(i[12],mix[ 4]);
+ out[ 9] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[ 9],mix[ 5]);
+ b = GMUL(i[10],mix[ 6]);
+ c = GMUL(i[11],mix[ 7]);
+ d = GMUL(i[12],mix[ 8]);
+ out[10] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[ 9],mix[ 9]);
+ b = GMUL(i[10],mix[10]);
+ c = GMUL(i[11],mix[11]);
+ d = GMUL(i[12],mix[12]);
+ out[11] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[ 9],mix[13]);
+ b = GMUL(i[10],mix[14]);
+ c = GMUL(i[11],mix[15]);
+ d = GMUL(i[12],mix[16]);
+ out[12] = XOR(XOR(a,b),XOR(c,d));
+
+
+ a = GMUL(i[13],mix[ 1]);
+ b = GMUL(i[14],mix[ 2]);
+ c = GMUL(i[15],mix[ 3]);
+ d = GMUL(i[16],mix[ 4]);
+ out[13] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[13],mix[ 5]);
+ b = GMUL(i[14],mix[ 6]);
+ c = GMUL(i[15],mix[ 7]);
+ d = GMUL(i[16],mix[ 8]);
+ out[14] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[13],mix[ 9]);
+ b = GMUL(i[14],mix[10]);
+ c = GMUL(i[15],mix[11]);
+ d = GMUL(i[16],mix[12]);
+ out[15] = XOR(XOR(a,b),XOR(c,d));
+ a = GMUL(i[13],mix[13]);
+ b = GMUL(i[14],mix[14]);
+ c = GMUL(i[15],mix[15]);
+ d = GMUL(i[16],mix[16]);
+ out[16] = XOR(XOR(a,b),XOR(c,d));
+
+ return out;
+end
+
+local keyRound = function(key,round)
+ local i=(round-1)*32;
+ local out=key;
+ print("Doing keyRound on key:")
+ PrintTable(key)
+ print("key[i+1]=")
+ print(key[i+1])
+ print("SBOX[out[30+i]]=")
+ print(SBOX[out[30+i]])
+ print("out[30+i]=")
+ print(out[30+i])
+ print("RCON[round]=")
+ print(RCON[round])
+ out[33+i] = XOR(key[ 1+i],XOR(SBOX[key[30+i]],RCON[round]));
+ out[34+i] = XOR(key[ 2+i],SBOX[key[31+i]]);
+ out[35+i] = XOR(key[ 3+i],SBOX[key[32+i]]);
+ out[36+i] = XOR(key[ 4+i],SBOX[key[29+i]]);
+
+ out[37+i] = XOR(out[33+i],key[ 5+i]);
+ out[38+i] = XOR(out[34+i],key[ 6+i]);
+ out[39+i] = XOR(out[35+i],key[ 7+i]);
+ out[40+i] = XOR(out[36+i],key[ 8+i]);
+
+ out[41+i] = XOR(out[37+i],key[ 9+i]);
+ out[42+i] = XOR(out[38+i],key[10+i]);
+ out[43+i] = XOR(out[39+i],key[11+i]);
+ out[44+i] = XOR(out[40+i],key[12+i]);
+
+ out[45+i] = XOR(out[41+i],key[13+i]);
+ out[46+i] = XOR(out[42+i],key[14+i]);
+ out[47+i] = XOR(out[43+i],key[15+i]);
+ out[48+i] = XOR(out[44+i],key[16+i]);
+
+
+ out[49+i] = XOR(SBOX[out[45+i]],key[17+i]);
+ out[50+i] = XOR(SBOX[out[46+i]],key[18+i]);
+ out[51+i] = XOR(SBOX[out[47+i]],key[19+i]);
+ out[52+i] = XOR(SBOX[out[48+i]],key[20+i]);
+
+ out[53+i] = XOR(out[49+i],key[21+i]);
+ out[54+i] = XOR(out[50+i],key[22+i]);
+ out[55+i] = XOR(out[51+i],key[23+i]);
+ out[56+i] = XOR(out[52+i],key[24+i]);
+
+ out[57+i] = XOR(out[53+i],key[25+i]);
+ out[58+i] = XOR(out[54+i],key[26+i]);
+ out[59+i] = XOR(out[55+i],key[27+i]);
+ out[60+i] = XOR(out[56+i],key[28+i]);
+
+ out[61+i] = XOR(out[57+i],key[29+i]);
+ out[62+i] = XOR(out[58+i],key[30+i]);
+ out[63+i] = XOR(out[59+i],key[31+i]);
+ out[64+i] = XOR(out[60+i],key[32+i]);
+
+ return out;
+end
+
+local keyExpand = function(key)
+ local bytes = Array.copy(key);
+
+ for i=1,7 do
+ keyRound(bytes,i);
+ end
+
+ local keys = {};
+
+ keys[ 1] = Array.slice(bytes,1,16);
+ keys[ 2] = Array.slice(bytes,17,32);
+ keys[ 3] = Array.slice(bytes,33,48);
+ keys[ 4] = Array.slice(bytes,49,64);
+ keys[ 5] = Array.slice(bytes,65,80);
+ keys[ 6] = Array.slice(bytes,81,96);
+ keys[ 7] = Array.slice(bytes,97,112);
+ keys[ 8] = Array.slice(bytes,113,128);
+ keys[ 9] = Array.slice(bytes,129,144);
+ keys[10] = Array.slice(bytes,145,160);
+ keys[11] = Array.slice(bytes,161,176);
+ keys[12] = Array.slice(bytes,177,192);
+ keys[13] = Array.slice(bytes,193,208);
+ keys[14] = Array.slice(bytes,209,224);
+ keys[15] = Array.slice(bytes,225,240);
+
+ return keys;
+
+end
+
+local addKey = Array.XOR;
+
+
+
+local AES = {};
+
+AES.blockSize = 16;
+
+AES.encrypt = function(key,block)
+ print("Calling keyExpand on :")
+ PrintTable(key)
+ local key = keyExpand(key);
+
+ --round 0
+ block = addKey(block,key[1]);
+
+ print("block is:")
+ PrintTable(block)
+
+ --round 1
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[2]);
+
+ --round 2
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[3]);
+
+ --round 3
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[4]);
+
+ --round 4
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[5]);
+
+ --round 5
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[6]);
+
+ --round 6
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[7]);
+
+ --round 7
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[8]);
+
+ --round 8
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[9]);
+
+ --round 9
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[10]);
+
+ --round 10
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[11]);
+
+ --round 11
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[12]);
+
+ --round 12
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[13]);
+
+ --round 13
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = mixCol(block,MIXTABLE);
+ block = addKey(block,key[14]);
+
+ --round 14
+ block = byteSub(block,SBOX);
+ block = shiftRow(block,ROW_SHIFT);
+ block = addKey(block,key[15]);
+
+ return block;
+
+end
+
+AES.decrypt = function(key,block)
+
+ local key = keyExpand(key);
+
+ --round 0
+ block = addKey(block,key[15]);
+
+ --round 1
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[14]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 2
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[13]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 3
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[12]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 4
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[11]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 5
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[10]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 6
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[9]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 7
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[8]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 8
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[7]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 9
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[6]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 10
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[5]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 11
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[4]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 12
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[3]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 13
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[2]);
+ block = mixCol(block,IMIXTABLE);
+
+ --round 14
+ block = shiftRow(block,IROW_SHIFT);
+ block = byteSub(block,ISBOX);
+ block = addKey(block,key[1]);
+
+ return block;
+end
+
+return AES;
diff --git a/gamemode/shared/concommands.lua b/gamemode/shared/concommands.lua
new file mode 100644
index 0000000..b4e844a
--- /dev/null
+++ b/gamemode/shared/concommands.lua
@@ -0,0 +1,28 @@
+--[[
+ Various console command helper functions
+]]
+
+local fuzzel = include("fuzzel.lua")
+
+local concmd = {}
+
+function concmd.AutocompleteFunction(...)
+ local opt = {...}
+ opt = type(opt[1]) == "table" and opt[1] or opt
+ return function(cmd,strargs)
+ --Remove spaces and quotes, since we don't want to match them
+ strargs = string.gsub(strargs,"[\" ]","")
+ --Find the options that most closely resemble our command so far
+ local sorted = fuzzel.fad(strargs,opt)
+ --Add quotes if needed, and preppend the command to each option
+ for k,v in pairs(sorted) do
+ if string.find(v," ") ~= nil then
+ sorted[k] = "\"" .. v .. "\""
+ end
+ sorted[k] = cmd .. " " .. sorted[k]
+ end
+ return sorted
+ end
+end
+
+return concmd
diff --git a/gamemode/shared/fuzzel.lua b/gamemode/shared/fuzzel.lua
new file mode 100644
index 0000000..6aad45f
--- /dev/null
+++ b/gamemode/shared/fuzzel.lua
@@ -0,0 +1,286 @@
+--[[
+ Fuzzel v1.3 - Alexander "Apickx" Pickering
+ Entered into the public domain June 2, 2016
+ You are not required to, but consider putting a link to the source in your file's comments!
+
+ Some helper functions for calculateing distance between two strings
+
+ Provides:
+ fuzzel.LevenshteinDistance_extended(string_first, string_second, number_addcost, number_substituecost, number_deletecost)
+ Calculates the Levenshtein Distance between two strings, useing the costs given. "Real" Levenshtein Distance uses values 1,1,1 for costs.
+ returns number_distance
+
+ fuzzel.LevenshteinDistance(string_first, strings_second)
+ Calculates the "real" Levenshtein Distance
+ returns number_distance
+
+ fuzzel.LevensteinRatio(string_first, string_second)
+ The Levenshtein Ratio divided by the first string's length. Useing a ratio is a decent way to determin if a spelling is "close enough"
+ returns number_distance
+
+ fuzzel.DamerauLevenshteinDistance_extended(string_first, string_second, number_addcost, number_substituecost, number_deletecost, number_transpositioncost)
+ Damerau-Levenshtein Distance is almost exactly like Levenshtein Distance, with the caveat that two letters next to each other, with swapped positions only counts as "one" cost (in "real" Damerau-Levenshtein Distance)
+ returns number
+
+ fuzzel.DamerauLevenshteinDistance(stirng_first, strings_second)
+ Calculates the "real" Damerau-Levenshtein Distance
+ returns number
+
+ fuzzel.DamerauLevenshteinRatio(string_first, string_second)
+ The Damerau-Levenshtein Distance divided by the first string's length
+ returns number_ratio
+
+ fuzzel.HammingDistance(string_first, string_second)
+ Purely the number of substitutions needed to change one string into another. Note that both strings must be the same length.
+ returns number_distance
+
+ fuzzel.HammingRatio(string_first, string_second)
+ The hamming distance divided by the length of the first string
+ returns number_ratio
+
+ fuzzel.FuzzyFindDistance(string_needle, vararg_in)
+ in may be either a table, or a list of arguments. fuzzel.FuzzySearchDistance will find the string that most closely resembles needle, based on Damerau-Levenshtein Distance. If multiple options have the same distance, it will return the first one encountered (This may not be in any sort of order!)
+ returns string_closest, number_distance
+
+ fuzzel.FuzzyFindRatio(string_needle, vararg_in)
+ in may be either a table, or a list of arguments. Same as above, except it returns the string with the closest Damerau-Levenshtein ratio.
+ returns string_closest, nubmer_ratio
+
+ fuzzel.FuzzySortDistance(string_needle, vararg_in)
+ Sorts either the table, or the arguments, and returns a table. Uses Damerau-Levenshtein Distance
+ returns table_sorted
+
+ fuzzel.FuzzySortRatio(string needle, vararg_in)
+ Same as above, but uses Damerau-Levenshtein Ratio instead
+ returns table_sorted
+
+ fuzzel.FuzzyAutocompleteDistance(string_needle, vararg in)
+ vararg_in can be either a table, or a list of entries, this will fuzzy sort based on the length of the input, which makes it better at autocompletion than fuzzy sorting. Uses Damerau-Levenshtein Distance.
+ returns table_sorted
+
+ fuzzel.FuzzyAutocompleteRatio(string_needle, vararg_in)
+ Same as above, but uses DamerauLevenshteinRatio
+ returns table_sorted
+
+ Example:
+ Returns a function that will return the closest string to the string it was passed
+ -----------------FuzzelExample.lua------------------
+ --Include the module
+ local fuzzel = require("fuzzel.lua")
+
+ --A couple of options
+ local options = {
+ "Fat Cat",
+ "Lazy Dog",
+ "Brown Fox",
+ }
+
+ --And use it, to see what option closest matches "Lulzy Cat"
+ local close,distance = fuzzel.FuzzyFindDistance("Lulzy Cat", options)
+ print("\"Lulzy Cat\" is close to \"" .. close .. "\", distance:" .. distance)
+
+ --Sort the options to see the order in which they most closely match "Frag God"
+ print("\"Frag God\" is closest to:")
+ for k,v in ipairs(fuzzel.FuzzySortRatio("Frag God",options)) do
+ print(k .. "\t:\t" .. v)
+ end
+ -------------End FuzzelExample.lua------------------
+ Outputs:
+ "Lulzy Cat" is close to "Fat Cat"
+ "Frag God" is closest to:
+ 1 : Fat Cat
+ 2 : Lazy Dog
+ 3 : Brown Fox
+
+ Some easy-to-use mnemonics
+ fuzzel.ld_e = fuzzel.LevenshteinDistance_extended
+ fuzzel.ld = fuzzel.LevenshteinDistance
+ fuzzel.lr = fuzzel.LevensteinRatio
+ fuzzel.dld_e = fuzzel.DamerauLevenshteinDistance_extended
+ fuzzel.dld = fuzzel.DamerauLevenshteinDistance
+ fuzzel.dlr = fuzzel.DamerauLevenshteinRatio
+ fuzzel.hd = fuzzel.HammingDistance
+ fuzzel.hr = fuzzel.HammingRatio
+ fuzzel.ffd = fuzzel.FuzzyFindDistance
+ fuzzel.ffr = fuzzel.FuzzyFindRatio
+ fuzzel.fsd = fuzzel.FuzzySortDistance
+ fuzzel.fsr = fuzzel.FuzzySortRatio
+ fuzzel.fad = fuzzel.FuzzyAutocompleteDistance
+ fuzzel.far = fuzzel.FuzzyAutocompleteRatio
+
+]]--You probably don't want to touch anything past this point
+
+--Assign locals to these to the minifier can compress the file better
+local strlen,chrat,min,asrt,prs,iprs,typ,upack,tblins,tblsrt,strsub,tru,fal = string.len,string.byte,math.min,assert,pairs,ipairs,type,unpack,table.insert,table.sort,string.sub,true,false
+
+local fuzzel = {}
+
+--A clever way to allow the minifier to minify function names, this basically just assigns variables with their string equivalent.
+local da, le, di, ra, fu, fi, so, ex, ha, au = "Damerau", "Levenshtein", "Distance", "Ratio", "Fuzzy", "Find", "Sort", "_extended", "Hamming", "Autocomplete"
+local LevenshteinDistance_extended,LevenshteinDistance,LevenshteinRatio,DamerauLevenshteinDistance_extended,DamerauLevenshteinDistance,DamerauLevenshteinRatio,FuzzyFindDistance,FuzzyFindRatio,FuzzySortDistance,FuzzySortRatio,HammingDistance,HammingRatio,FuzzyAutocompleteDistance,FuzzyAutocompleteRatio = le..di..ex,le..di,le..ra,da..le..di..ex,da..le..di,da..le..ra,fu..fi..di,fu..fi..ra,fu..so..di,fu..so..ra,ha..di,ha..ra,fu..au..di,fu..au..ra
+
+local function genericDistance( stringa, stringb, addcost, subcost, delcost, ...)
+ local arg = {...}
+
+ --Length of each string
+ local salen, sblen = strlen(stringa), strlen(stringb)
+
+ --Create a 0 matrix the size of len(a) x len(b)
+ local dyntbl = {}
+ for i = 0,salen do
+ dyntbl[i] = {}
+ for j = 0,sblen do
+ dyntbl[i][j] = 0
+ end
+ end
+
+ --Initalize the matrix
+ for i = 1,salen do
+ dyntbl[i][0] = i
+ end
+ for j = 1,sblen do
+ dyntbl[0][j] = j
+ end
+
+ --And build up the matrix based on costs-so-far
+ for j = 1,sblen do
+ for i = 1,salen do
+ local ca,cb = chrat(stringa,i),chrat(stringb,j)
+ dyntbl[i][j] = min(
+ dyntbl[i-1][j] + delcost, --deletion
+ dyntbl[i][j-1] + addcost, --insertion
+ dyntbl[i-1][j-1] + (ca == cb and 0 or subcost) --substituion
+ )
+ if arg[1] and i > 1 and j > 1 and ca == chrat(stringb,j-1) and chrat(stringa,i-1) == cb then
+ dyntbl[i][j] = min(dyntbl[i][j],
+ dyntbl[i-2][j-2] + (ca == cb and 0 or arg[2])) --transposition
+ end
+ end
+ end
+
+ return dyntbl[salen][sblen]
+end
+
+fuzzel[LevenshteinDistance_extended] = function(stringa, stringb, addcost, subcost, delcost)
+ return genericDistance(stringa, stringb, addcost, subcost, delcost)
+end
+fuzzel.ld_e = fuzzel[LevenshteinDistance_extended]
+
+fuzzel[LevenshteinDistance] = function(stringa,stringb)
+ return fuzzel.ld_e(stringa,stringb,1,1,1)
+end
+fuzzel.ld = fuzzel[LevenshteinDistance]
+
+fuzzel[LevenshteinRatio] = function(stringa,stringb)
+ return fuzzel.ld(stringa,stringb) / strlen(stringa)
+end
+fuzzel.lr = fuzzel[LevenshteinRatio]
+
+fuzzel[DamerauLevenshteinDistance_extended] = function(stringa, stringb, addcost, subcost, delcost, trncost)
+ return genericDistance(stringa,stringb,addcost,subcost,delcost,tru,trncost)
+end
+fuzzel.dld_e = fuzzel[DamerauLevenshteinDistance_extended]
+
+fuzzel[DamerauLevenshteinDistance] = function(stringa,stringb)
+ return fuzzel.dld_e(stringa,stringb,1,1,1,1)
+end
+fuzzel.dld = fuzzel[DamerauLevenshteinDistance]
+
+fuzzel[DamerauLevenshteinRatio] = function(stringa,stringb)
+ return fuzzel.dld(stringa,stringb) / strlen(stringa)
+end
+fuzzel.dlr = fuzzel[DamerauLevenshteinRatio]
+
+fuzzel[HammingDistance] = function(stringa,stringb)
+ local len,dist = strlen(stringa),0
+ asrt(len == strlen(stringb), ha.." "..di.." cannot be calculated on two strings of different lengths:\"" .. stringa .. "\" \"" .. stringb .. "\"")
+ for i = 1,len do
+ dist = dist + ((chrat(stringa,i) ~= chrat(stringb,i)) and 1 or 0)
+ end
+ return dist
+end
+fuzzel.hd = fuzzel[HammingDistance]
+
+fuzzel[HammingRatio] = function(stringa,stringb)
+ return fuzzel.hd(stringa,stringb) / strlen(stringa)
+end
+fuzzel.hr = fuzzel[HammingRatio]
+
+local function FuzzySearch(str,func,...)
+ local arg = {...}
+
+ --Allow varargs, or a table
+ local looparg = typ(arg[1]) == "table" and arg[1] or arg
+
+ --Find the string with the shortest distance to the string we were supplied
+ local tmin,sout = func(looparg[1],str),looparg[1]
+ for k,v in prs(looparg) do
+ local t = func(v,str)
+ if t <= tmin then
+ tmin,sout = t,k
+ end
+ end
+ return looparg[sout], tmin
+end
+
+fuzzel[FuzzyFindDistance] = function(str,...)
+ return upack{FuzzySearch(str,fuzzel.dld,...)}
+end
+fuzzel.ffd = fuzzel[FuzzyFindDistance]
+
+fuzzel[FuzzyFindRatio] = function(str,...)
+ return upack{FuzzySearch(str,fuzzel.dlr,...)}
+end
+
+local function FuzzySort(str, func, short, ...)
+ local arg = {...}
+
+ --allow varargs, or a table
+ local looparg = typ(arg[1]) == "table" and arg[1] or arg
+
+ --Roughly sort everything by it's distance to the string
+ local usorted,sorted,otbl,slen = {},{},{},strlen(str)
+ for k,v in prs(looparg) do
+ local sstr = short and strsub(v,0,slen) or v
+ local dist = func(str,sstr)
+ if usorted[dist] == nil then
+ usorted[dist] = {}
+ tblins(sorted,dist)
+ end
+ tblins(usorted[dist],v)
+ end
+
+ --Actually sort them into something can can be iterated with ipairs
+ tblsrt(sorted)
+
+ --Then build our output table
+ for k,v in iprs(sorted) do
+ for i,j in prs(usorted[v]) do
+ tblins(otbl,j)
+ end
+ end
+ return otbl
+end
+fuzzel.ffr = fuzzel[FuzzyFindRatio]
+
+fuzzel[FuzzySortDistance] = function(str,...)
+ return FuzzySort(str,fuzzel.dld,fal,...)
+end
+fuzzel.fsd = fuzzel[FuzzySortDistance]
+
+fuzzel[FuzzySortRatio] = function(str,...)
+ return FuzzySort(str,fuzzel.dlr,fal,...)
+end
+fuzzel.fsr = fuzzel[FuzzySortRatio]
+
+fuzzel[FuzzyAutocompleteDistance] = function(str, ...)
+ return FuzzySort(str,fuzzel.dld,tru,...)
+end
+fuzzel.fad = fuzzel[FuzzyAutocompleteDistance]
+
+fuzzel[FuzzyAutocompleteRatio] = function(str,...)
+ return FuzzySort(str,fuzzel.dlr,tru,...)
+end
+fuzzel.far = fuzzel[FuzzyAutocompleteRatio]
+
+return fuzzel
diff --git a/gamemode/shared/inventory.lua b/gamemode/shared/inventory.lua
new file mode 100644
index 0000000..42f4516
--- /dev/null
+++ b/gamemode/shared/inventory.lua
@@ -0,0 +1,213 @@
+
+print("Hello from inventory.lua!")
+local pmeta = FindMetaTable("Player")
+local emeta = FindMetaTable("Entity")
+local invfuncs = include("inventory_common.lua")
+
+--A 2d array of the inventory.
+pmeta.Inventory = {}
+
+--each backpack has 1:a tbl containing items or false, 2: a tbl {width,height} and 3:name
+pmeta.Inventory.Backpacks = {}
+--Eqiped stuff at base, player has 1=Head, 2=Body, 3=Legs, 4=Boots, 5=Gloves, 6=Left Hand, 7=Right Hand
+pmeta.Inventory.Equiped = {}
+local equipedslots = {
+ "Head","Body","Legs","Boots","Gloves","Left","Right"
+}
+for _,v in pairs(equipedslots) do
+ pmeta.Inventory.Equiped[v] = false
+end
+
+function pmeta:PutInvItem(backpack,x,y,item)
+ invfuncs.PutItemInBackpack(self.Inventory.Backpacks[backpack],x,y,item)
+end
+
+function pmeta:FindSpotForItem(item)
+ for n,v in pairs(self.Inventory.Backpacks) do
+ for row = 1,v[2][2] do
+ for col = 1,v[2][1] do
+ if self:CanFitInBackpack(v,row,col,item) then
+ return row,col,n
+ end
+ end
+ end
+ end
+end
+
+function pmeta:GiveItem(item)
+ local x,y,b = self:FindSpotForItem(item)
+ self:PutInvItem(b,x,y,item)
+ self:SynchronizeInventory()
+end
+
+function pmeta:CanFitInBackpack(backpack,x,y,item)
+ return invfuncs.CanFitInBackpack(backpack,x,y,item)
+end
+
+if SERVER then
+ util.AddNetworkString("synchinventory")
+ util.AddNetworkString("moveitem")
+ util.AddNetworkString("equipitem")
+ util.AddNetworkString("unequipitem")
+end
+
+net.Receive("unequipitem",function(len,ply)
+ local itemslot = net.ReadString()
+ local tobackpack = net.ReadUInt(16)
+ local topos = {}
+ topos[1] = net.ReadUInt(16)
+ topos[2] = net.ReadUInt(16)
+ local item = ply.Inventory.Equiped[itemslot]
+ if ply:CanFitInBackpack(
+ ply.Inventory.Backpacks[tobackpack],
+ topos[1],
+ topos[2],
+ item
+ ) then
+ ply.Inventory.Equiped[itemslot] = false
+ ply:PutInvItem(tobackpack,topos[1],topos[2],item)
+ ply:SynchronizeInventory()
+ end
+end)
+
+net.Receive("equipitem",function(len,ply)
+ local backpacknum = net.ReadUInt(16)
+ local frompos = {}
+ frompos[1] = net.ReadUInt(16)
+ frompos[2] = net.ReadUInt(16)
+ local equippos = net.ReadString()
+ local item = ply.Inventory.Backpacks[backpacknum][1][frompos[1]][frompos[2]]
+ if item.Equipable ~= nil and item.Equipable == equippos then
+ --Remove from the backpack
+ for k = 1,#item.Shape do
+ for i = 1,#(item.Shape[k]) do
+ if k == 1 and i == 1 then continue end
+ ply.Inventory.Backpacks[backpacknum][1][frompos[1] + k - 1][frompos[2] + i - 1] = false
+ end
+ end
+ ply.Inventory.Backpacks[backpacknum][1][frompos[1]][frompos[2]] = false
+ ply.Inventory.Equiped[equippos] = item
+ if item.onEquip ~= nil then
+ item:onEquip(ply)
+ end
+ ply:SynchronizeInventory()
+ end
+end)
+
+net.Receive("moveitem",function(len,ply)
+ local froment = net.ReadEntity()
+ local toent = net.ReadEntity()
+
+ local frombackpack = net.ReadUInt(16)
+ local tobackpack = net.ReadUInt(16)
+
+ local frompos = {net.ReadUInt(16),net.ReadUInt(16)}
+ local topos = {net.ReadUInt(16),net.ReadUInt(16)}
+
+ print("Moveing from ",frompos[1],frompos[2],"to",topos[1],topos[2])
+
+ if froment:IsPlayer() and toent:IsPlayer() and (froment ~= toent) then--Just don't allow stealing between players, anything else is fine
+ ply:PrintMessage( HUD_PRINTCENTER, "You can't steal from this person!" )
+ return
+ end
+ print("Passed the stealing check")
+ local item = froment.Inventory.Backpacks[frombackpack][1][frompos[1]][frompos[2]]
+
+ --Set the shape it was at to false
+ for k = 1,#item.Shape do
+ for i = 1,#(item.Shape[k]) do
+ if k == 1 and i == 1 then continue end
+ froment.Inventory.Backpacks[frombackpack][1][frompos[1] + k - 1][frompos[2] + i - 1] = false
+ end
+ end
+ froment.Inventory.Backpacks[frombackpack][1][frompos[1]][frompos[2]] = false
+ print("Set shape to false")
+ --now check if it can fit in the backpack
+ if invfuncs.CanFitInBackpack(toent.Inventory.Backpacks[tobackpack],topos[1],topos[2],item) then
+ print("It can fit there")
+ invfuncs.PutItemInBackpack(toent.Inventory.Backpacks[tobackpack],topos[1],topos[2],item)
+ else
+ invfuncs.PutItemInBackpack(froment.Inventory.Backpacks[frombackpack],frompos[1],frompos[2],item)
+ end
+ froment:SynchronizeInventory()
+ toent:SynchronizeInventory()
+end)
+
+function pmeta:LoadInventory(json)
+ local reinv = util.JSONToTable(json)
+ for k,v in pairs(reinv) do
+ self.Inventory[k] = v
+ end
+ self:SynchronizeInventory()
+end
+
+function pmeta:SynchronizeInventory()
+ print("Player synchronize called")
+ net.Start("synchinventory")
+ net.WriteEntity(self)
+ net.WriteFloat(#self.Inventory.Backpacks)
+ for k,v in pairs(self.Inventory.Backpacks) do
+ invfuncs.SerializeBackpack(v)
+ end
+ for k,v in pairs(equipedslots) do
+ if self.Inventory.Equiped and self.Inventory.Equiped[v] ~= false then
+ net.WriteString(v)
+ local data = self.Inventory.Equiped[v]:Serialize()
+ net.WriteString(self.Inventory.Equiped[v].Name)
+ net.WriteUInt(#data,32)
+ net.WriteData(data,#data)
+ end
+ end
+ net.WriteString("END_EQUIPED")
+ net.Send(self)
+end
+if CLIENT then
+ net.Receive("synchinventory",function(len,ply)
+ if LocalPlayer().invdisplays == nil then
+ LocalPlayer().invdisplays = {}
+ end
+ local what = net.ReadEntity()
+ what.Inventory.Backpacks = {}
+ local numbackpacks = net.ReadFloat()
+ for k = 1,numbackpacks do
+ local tbackpack = invfuncs.DeSerializeBackpack()
+ table.insert(what.Inventory.Backpacks,tbackpack)
+ end
+ local neq = net.ReadString()
+ local updated_slots = {}
+ while neq ~= "END_EQUIPED" do
+ local itemslot = neq
+ local itemname = net.ReadString()
+ local itemdata = net.ReadData(net.ReadUInt(32))
+ local item = ART.GetItemByName(itemname):DeSerialize(itemdata)
+ what.Inventory.Equiped[itemslot] = item
+ updated_slots[itemslot] = true
+ neq = net.ReadString()
+ end
+ if what.Inventory.Equiped ~= nil then
+ for k,v in pairs(equipedslots) do
+ if updated_slots[v] then continue end
+ what.Inventory.Equiped[v] = false
+ end
+ end
+ local discopy = LocalPlayer().invdisplays
+ LocalPlayer().invdisplays = {}
+ PrintTable(discopy)
+ for k,ptbl in pairs(discopy) do
+ if not ptbl.panel:IsValid() then continue end
+ if ptbl.panel.Close ~= nil then
+ ptbl.panel:Close()
+ else
+ print(ptbl.panel)
+ error("panel has no close method")
+ ptbl.panel:Remove()
+ end
+ ptbl.redraw()
+ end
+ end)
+end
+
+concommand.Add("artery_showinventory",function(ply,cmd,args)
+ PrintTable(ply.Inventory)
+ PrintTable(ply.ClientInventory)
+end)
diff --git a/gamemode/shared/inventory_common.lua b/gamemode/shared/inventory_common.lua
new file mode 100644
index 0000000..e86d0a6
--- /dev/null
+++ b/gamemode/shared/inventory_common.lua
@@ -0,0 +1,205 @@
+--[[
+ Some functions that are needed multiple places in the code, to deal with player inventories.
+]]
+local invfuncs = {}
+
+--Forcibly put an item in a backpack, you should check to make sure there's room first
+invfuncs.PutItemInBackpack = function(backpack,x,y,item)
+ backpack[1][x][y] = item
+ for k = 1,#item.Shape do
+ for i = 1,#(item.Shape[k]) do
+ if k == 1 and i == 1 then continue end
+ backpack[1][x + k - 1][y + i - 1] = item.Shape[k][i]
+ end
+ end
+end
+
+--Writes a backpack to the net stream
+invfuncs.SerializeBackpack = function(backpack)
+ net.WriteString(backpack[3]) --Name
+ net.WriteUInt(backpack[2][1],16) --width
+ net.WriteUInt(backpack[2][2],16) --height
+ for k,v in pairs(backpack[1]) do
+ for i,j in pairs(v) do
+ if type(j) ~= "table" then continue end
+ net.WriteString(j.Name)
+ net.WriteUInt(k,16)
+ net.WriteUInt(i,16)
+ local data = j:Serialize()
+ net.WriteUInt(#data,32)
+ net.WriteData(data,#data)
+ end
+ end
+ net.WriteString("END_ITEMS")
+end
+
+--Loads a backpack from the net stream
+invfuncs.DeSerializeBackpack = function()
+ local backpackname = net.ReadString()
+ local width = net.ReadUInt(16)
+ local height = net.ReadUInt(16)
+ --Build the backpack
+ local tb = {}
+ tb[1] = {}
+ tb[2] = {width,height}
+ tb[3] = backpackname
+ for x = 1,width do
+ tb[1][x] = {}
+ for y = 1,height do
+ tb[1][x][y] = false
+ end
+ end
+
+ local nitemname = net.ReadString()
+ while nitemname ~= "END_ITEMS" do
+ local xpos = net.ReadUInt(16)
+ local ypos = net.ReadUInt(16)
+ local data = net.ReadData(net.ReadUInt(32))
+ local nitem = ART.GetItemByName(nitemname):DeSerialize(data)
+ invfuncs.PutItemInBackpack(tb,xpos,ypos,nitem)
+ nitemname = net.ReadString()
+ end
+
+ return tb
+
+end
+
+--Checks to see if an item can fit in the backpack at a certain position
+invfuncs.CanFitInBackpack = function(backpack,x,y,item)
+ for k,v in pairs(item.Shape) do
+ for i,j in pairs(v) do
+ if not j then continue end
+ if backpack[1][x + k - 1] == nil then
+ return false
+ end
+ if backpack[1][x + k - 1][y + i - 1] or backpack[1][x + k - 1][y + i - 1] == nil then
+ return false
+ end
+ end
+ end
+ return true
+end
+
+--Creates a new backpack, this is NOT called when players join the server, even new ones.
+invfuncs.CreateBackpack = function(name,width,height)
+ local backpack = {}
+ backpack[1] = {}
+ backpack[2] = {width,height}
+ backpack[3] = name
+ for i = 1,width do --the width of the backpack.
+ backpack[1][i] = {}
+ end
+ for k,v in pairs(backpack[1]) do
+ for i = 1,height do --the height of the backpack.
+ backpack[1][k][i] = false
+ end
+ end
+ return backpack
+end
+
+--Displays a dropdown of options under the players mouse, if the option is clicked, does the function
+--Requires a table of strings to functions, or strings to tables of strings to functions.
+--Be careful not to make this a recursive table.
+local function createMenuFor(menu, tbl)
+ for k,v in pairs(tbl) do
+ if(isfunction(v)) then --This is a dead-end, add the menu
+ local thisoption = menu:AddOption(k,v)
+ else --Otherwise it should be a table, recursively call to create
+ local submenu = menu:AddSubMenu(k)
+ createMenuFor(submenu,v)
+ end
+ end
+end
+
+--Draws a backpack on the dpanel, client side only
+invfuncs.DrawBackpackOnDPanel = function(dp, backpack, backpacknum, tent)
+ local width = ScrW()
+ local height = ScrH()
+ local slotsize = math.Round(width / 32)
+ local backgrid = vgui.Create( "DGrid", dp )
+ backgrid:SetPos( 10, 30 )
+ backgrid:SetCols( backpack[2][1] )
+ backgrid:SetColWide( backpack[2][2] )
+ backgrid:Dock(FILL)
+ for i = 1,#(backpack[1]) do
+ for j = 1,#(backpack[1][i]) do
+ local item = backpack[1][j][i]
+ if type(backpack[1][j][i]) == "table" then
+ local itemwidth = 0
+ for _,l in pairs(item.Shape) do
+ itemwidth = math.Max(itemwidth,#l)
+ end
+ local itemheight = #item.Shape
+ local invicon = vgui.Create( "DButton", dp )
+ invicon:SetSize(slotsize * itemwidth, slotsize * itemheight)
+ invicon:SetPos(slotsize * (i - 1), slotsize * (j - 1))
+ invicon:SetText(item.Name)
+ if item.Tooltip then
+ invicon:SetTooltip(item.Tooltip)
+ end
+ --invicon.Paint = function(self, w, h) draw.RoundedBox(4, 0,0,w,h,Color(0,100,0)) end
+ invicon.DoClick = function()
+ if not item.GetOptions then return end
+ local menu = vgui.Create("DMenu")
+ createMenuFor(menu,item:GetOptions())
+ menu:Open()
+ end
+ invicon.Item = item
+ invicon.invpos = {j,i}
+ invicon.ent = tent
+ invicon.backpacknum = backpacknum
+ invicon:Droppable("Inventory")
+ elseif not backpack[1][j][i] then
+ local emptyslot = vgui.Create("DPanel", dp)
+ emptyslot:SetSize(slotsize,slotsize)
+ emptyslot:SetPos(slotsize * (i - 1), slotsize * (j - 1))
+ --emptyslot.Paint = function(self, w, h) draw.RoundedBox(4, 0,0,w,h,Color(0,0,100)) end
+ emptyslot:Receiver( "Inventory", function( receiver, tableOfDroppedPanels, isDropped, menuIndex, mouseX, mouseY )
+ if not isDropped then return end
+ local icon = tableOfDroppedPanels[1]
+ local item = icon.Item
+ local curpos = icon.invpos
+ --Set the shape it was at to false
+ if not icon.wasequiped and icon.ent == tent then
+ assert(curpos ~= nil, "print curpos was nil when not equiped")
+ for k = 1,#item.Shape do
+ for l = 1,#(item.Shape[k]) do
+ if k == 1 and l == 1 then continue end
+ backpack[1][curpos[1] + k - 1][curpos[2] + l - 1] = false
+ end
+ end
+ backpack[1][curpos[1]][curpos[2]] = false
+ end
+ if invfuncs.CanFitInBackpack(backpack,j,i,item) then
+ local fromtbl = icon.invpos
+ local wasequiped = icon.wasequiped
+ if wasequiped then
+ net.Start("unequipitem")
+ net.WriteString(wasequiped)
+ net.WriteUInt(backpacknum,16)
+ net.WriteUInt(i,16)
+ net.WriteUInt(j,16)
+ net.SendToServer()
+ else
+ net.Start("moveitem")
+ net.WriteEntity(icon.ent) -- from ent
+ net.WriteEntity(tent) -- to ent
+ net.WriteUInt(icon.backpacknum,16) -- from backpack number
+ net.WriteUInt(backpacknum,16) -- to backpack number
+ net.WriteUInt(fromtbl[1],16) -- From position
+ net.WriteUInt(fromtbl[2],16)
+ net.WriteUInt(j,16) -- To position
+ net.WriteUInt(i,16)
+ net.SendToServer()
+ if item.onEquip ~= nil then
+ item:onEquip(LocalPlayer())
+ end
+ end
+ end
+ end, {} )
+ end
+ end
+ end
+end
+
+return invfuncs
diff --git a/gamemode/shared/itemcommon/common_inventory.lua b/gamemode/shared/itemcommon/common_inventory.lua
new file mode 100644
index 0000000..3f5fb3a
--- /dev/null
+++ b/gamemode/shared/itemcommon/common_inventory.lua
@@ -0,0 +1,9 @@
+--[[
+ Stores some common functions related to inventories
+]]
+local common = {}
+
+--Must have Serialize and Deseralize created before calling.
+function MakeInventoryable(item,shape,width,height,xpos,ypos)
+
+end
diff --git a/gamemode/shared/itemsystem/exampleitem.lua b/gamemode/shared/itemsystem/exampleitem.lua
new file mode 100644
index 0000000..f39a979
--- /dev/null
+++ b/gamemode/shared/itemsystem/exampleitem.lua
@@ -0,0 +1,25 @@
+--[[
+ An example item
+]]
+local item = {}
+
+item.Name = "Test item"
+
+item.Serialize = function(self)
+ print("Trying to serailize!")
+ return ""
+end
+
+item.DeSerialize = function(self,string)
+ print("Trying to deserialize!")
+ return self
+end
+
+item.Shape = {
+ {true},
+ {true},
+ {true},
+}
+
+print("Hello from exampleitem.lua")
+ART.RegisterItem(item)
diff --git a/gamemode/shared/itemsystem/scrapgun.lua b/gamemode/shared/itemsystem/scrapgun.lua
new file mode 100644
index 0000000..bf21b42
--- /dev/null
+++ b/gamemode/shared/itemsystem/scrapgun.lua
@@ -0,0 +1,60 @@
+--[[
+ An example item
+]]
+local item = {}
+
+--Required, a name, all item names must be unique
+item.Name = "Scrap gun"
+
+--Optional, a tooltip to display
+item.Tooltip = "A gun made from bits of scrap"
+
+--Required Returns the data needed to rebuild this item, should only contain the minimum data nessessary since this gets sent over the network
+item.Serialize = function(self)
+ print("Trying to serailize!")
+ return ""
+end
+
+--Required, Rebuilds the item from data created in Serialize, if the item is different from the "main" copy of the item, it should retun a tabl.Copy(self), with the appropriate fields set.
+item.DeSerialize = function(self,string)
+ print("Trying to deserialize!")
+ return self
+end
+
+--Optional, when the player clicks this item, a menu will show up, if the menu item is clicked, the function is ran. This is all run client side, so if you want it to do something, you'll need to use the net library.
+function item.GetOptions(self)
+ local options = {}
+ options["test"] = function() print("You pressed test!") end
+ options["toste"] = function() print("You pressed toste!") end
+ return options
+end
+
+--Required, the shape of this item.
+item.Shape = {
+ {true,true},
+ {true},
+}
+
+--Optional, If this item can be equiped in any player slots, put them here.
+item.Equipable = "Left"
+
+--Optional, what to do when the player clicks, and this item is in the slot in inventory
+item.onClick = function(self,owner)
+ print("pew pew!")
+end
+
+--Optional, if we should do something special on equip(like draw the PAC for this weapon)
+item.onEquip = function(self,who)
+ print("onEquip",who)
+ if CLIENT then print("onEquip client!") end
+ if SERVER then
+ PrintTable(pac)
+ --local outfit = pac.luadata.ReadFile("pac3/mech.txt")
+ --who:AttachPACPart(outfit)
+ --print("onEquip server!")
+ end
+end
+
+print("Hello from scrapgun.lua")
+--Don't forget to register the item!
+ART.RegisterItem(item)
diff --git a/gamemode/shared/loaditems.lua b/gamemode/shared/loaditems.lua
new file mode 100644
index 0000000..18260f2
--- /dev/null
+++ b/gamemode/shared/loaditems.lua
@@ -0,0 +1,55 @@
+--[[
+ This file loads in all the items
+]]
+local concmd = include("concommands.lua")
+--local autolua = include("../autolua.lua")
+print("Hello from LoadItems.lua!")
+ART.Items = {}
+local requiredfields = {
+ "Name",
+}
+local defaultfields = {
+ ["Serialize"] = function(self) return "" end,
+ ["DeSerialize"] = function(self,string) return self end,
+ ["Shape"] = {{true}},
+}
+function ART.RegisterItem(tbl)
+ print("Registering item:" .. tbl.Name)
+ for k,v in pairs(requiredfields) do
+ assert(tbl[v] ~= nil, "Attempted to register an item without field:" .. v)
+ end
+ assert(ART.Items[tbl.Name] == nil, "Attempted to register 2 items with the same name!")
+ for k,v in pairs(defaultfields) do
+ if tbl[k] == nil then
+ tbl[k] = v
+ end
+ end
+ ART.Items[tbl.Name] = tbl
+ print("Art is now:")
+ PrintTable(ART)
+end
+
+--autolua.AddLuaSHFolder("/shared/itemsystem")
+
+function ART.GiveItem(player,name)
+ assert(ART.Items[name] ~= nil, "Attempted to give a nil item!")
+ player:GiveItem(ART.Items[name])
+ player:SynchronizeInventory()
+end
+
+function ART.GetItemByName(name)
+ assert(ART.Items[name] ~= nil,"Attempted to get a nil item:" .. name)
+ return ART.Items[name]
+end
+
+concommand.Add("artery_printitems",function(ply,cmd,args)
+ if not ply:IsAdmin() then return end
+ print("Items table:")
+ PrintTable(ART.Items)
+end)
+
+concommand.Add("artery_giveitem",function(ply,cmd,args)
+ if not ply:IsAdmin() then return end
+ print("Trying to give an item:" .. args[1])
+ ART.GiveItem(ply,args[1])
+end, concmd.AutocompleteFunction(table.GetKeys(ART.Items)), "Give an item to the specified player, or yourself if no player is specified.")
diff --git a/gamemode/shared/lockbox/array.lua b/gamemode/shared/lockbox/array.lua
new file mode 100644
index 0000000..7ae89fc
--- /dev/null
+++ b/gamemode/shared/lockbox/array.lua
@@ -0,0 +1,211 @@
+print("Hello from array.lua!")
+local String = string
+local Bit = include("bit.lua");
+
+local XOR = Bit.bxor;
+
+local Array = {};
+
+Array.size = function(array)
+ return #array;
+end
+
+Array.fromString = function(string)
+ local bytes = {};
+
+ local i=1;
+ local byte = String.byte(string,i);
+ while byte ~= nil do
+ bytes[i] = byte;
+ i = i + 1;
+ byte = String.byte(string,i);
+ end
+
+ return bytes;
+
+end
+
+Array.toString = function(bytes)
+ local chars = {};
+ local i=1;
+
+ local byte = bytes[i];
+ while byte ~= nil do
+ chars[i] = String.char(byte);
+ i = i+1;
+ byte = bytes[i];
+ end
+
+ return table.concat(chars,"");
+end
+
+Array.fromStream = function(stream)
+ local array = {};
+ local i=1;
+
+ local byte = stream();
+ while byte ~= nil do
+ array[i] = byte;
+ i = i+1;
+ byte = stream();
+ end
+
+ return array;
+end
+
+Array.readFromQueue = function(queue,size)
+ local array = {};
+
+ for i=1,size do
+ array[i] = queue.pop();
+ end
+
+ return array;
+end
+
+Array.writeToQueue = function(queue,array)
+ local size = Array.size(array);
+
+ for i=1,size do
+ queue.push(array[i]);
+ end
+end
+
+Array.toStream = function(array)
+ local queue = Queue();
+ local i=1;
+
+ local byte = array[i];
+ while byte ~= nil do
+ queue.push(byte);
+ i=i+1;
+ byte = array[i];
+ end
+
+ return queue.pop;
+end
+
+
+local fromHexTable = {};
+for i=0,255 do
+ fromHexTable[String.format("%02X",i)]=i;
+ fromHexTable[String.format("%02x",i)]=i;
+end
+
+Array.fromHex = function(hex)
+ local array = {};
+
+ for i=1,String.len(hex)/2 do
+ local h = String.sub(hex,i*2-1,i*2);
+ array[i] = fromHexTable[h];
+ end
+
+ return array;
+end
+
+
+local toHexTable = {};
+for i=0,255 do
+ toHexTable[i]=String.format("%02X",i);
+end
+
+Array.toHex = function(array)
+ local hex = {};
+ local i = 1;
+
+ local byte = array[i];
+ while byte ~= nil do
+ hex[i] = toHexTable[byte];
+ i=i+1;
+ byte = array[i];
+ end
+
+ return table.concat(hex,"");
+
+end
+
+Array.concat = function(a,b)
+ local concat = {};
+ local out=1;
+
+ local i=1;
+ local byte = a[i];
+ while byte ~= nil do
+ concat[out] = byte;
+ i = i + 1;
+ out = out + 1;
+ byte = a[i];
+ end
+
+ local i=1;
+ local byte = b[i];
+ while byte ~= nil do
+ concat[out] = byte;
+ i = i + 1;
+ out = out + 1;
+ byte = b[i];
+ end
+
+ return concat;
+end
+
+Array.truncate = function(a,newSize)
+ local x = {};
+
+ for i=1,newSize do
+ x[i]=a[i];
+ end
+
+ return x;
+end
+
+Array.XOR = function(a,b)
+ local x = {};
+
+ for k,v in pairs(a) do
+ x[k] = XOR(v,b[k]);
+ end
+
+ return x;
+end
+
+Array.substitute = function(input,sbox)
+ local out = {};
+
+ for k,v in pairs(input) do
+ out[k] = sbox[v];
+ end
+
+ return out;
+end
+
+Array.permute = function(input,pbox)
+ local out = {};
+
+ for k,v in pairs(pbox) do
+ out[k] = input[v];
+ end
+
+ return out;
+end
+
+Array.copy = function(input)
+ local out = {};
+
+ for k,v in pairs(input) do
+ out[k] = v;
+ end
+ return out;
+end
+
+Array.slice = function(input,start,stop)
+ local out = {};
+
+ for i=start,stop do
+ out[i-start+1] = input[i];
+ end
+ return out;
+end
+
+
+return Array;
diff --git a/gamemode/shared/lockbox/base64.lua b/gamemode/shared/lockbox/base64.lua
new file mode 100644
index 0000000..3d9ffc3
--- /dev/null
+++ b/gamemode/shared/lockbox/base64.lua
@@ -0,0 +1,157 @@
+local String = string
+local Bit = include("bit.lua");
+
+local Array = include("array.lua");
+local Stream = include("stream.lua");
+
+local AND = Bit.band;
+local OR = Bit.bor;
+local NOT = Bit.bnot;
+local XOR = Bit.bxor;
+local LROT = Bit.lrotate;
+local RROT = Bit.rrotate;
+local LSHIFT = Bit.lshift;
+local RSHIFT = Bit.rshift;
+
+
+local SYMBOLS = {
+[0]="A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
+ "Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
+ "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
+ "w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"};
+
+local LOOKUP = {};
+
+for k,v in pairs(SYMBOLS) do
+ LOOKUP[k]=v;
+ LOOKUP[v]=k;
+end
+
+
+local Base64 = {};
+
+Base64.fromStream = function(stream)
+ local bits = 0x00;
+ local bitCount = 0;
+ local base64 = {};
+
+ local byte = stream();
+ while byte ~= nil do
+ bits = OR(LSHIFT(bits,8),byte);
+ bitCount = bitCount + 8;
+ while bitCount >= 6 do
+ bitCount = bitCount - 6;
+ local temp = RSHIFT(bits,bitCount);
+ table.insert(base64,LOOKUP[temp]);
+ bits = AND(bits,NOT(LSHIFT(0xFFFFFFFF,bitCount)));
+ end
+ byte = stream();
+ end
+
+ if (bitCount == 4) then
+ bits = LSHIFT(bits,2);
+ table.insert(base64,LOOKUP[bits]);
+ table.insert(base64,"=");
+ elseif (bitCount == 2) then
+ bits = LSHIFT(bits,4);
+ table.insert(base64,LOOKUP[bits]);
+ table.insert(base64,"==");
+ end
+
+ return table.concat(base64,"");
+end
+
+Base64.fromArray = function(array)
+ local bits = 0x00;
+ local bitCount = 0;
+ local base64 = {};
+
+ local ind = 1;
+
+ local byte = array[ind]; ind = ind + 1;
+ while byte ~= nil do
+ bits = OR(LSHIFT(bits,8),byte);
+ bitCount = bitCount + 8;
+ while bitCount >= 6 do
+ bitCount = bitCount - 6;
+ local temp = RSHIFT(bits,bitCount);
+ table.insert(base64,LOOKUP[temp]);
+ bits = AND(bits,NOT(LSHIFT(0xFFFFFFFF,bitCount)));
+ end
+ byte = array[ind]; ind = ind + 1;
+ end
+
+ if (bitCount == 4) then
+ bits = LSHIFT(bits,2);
+ table.insert(base64,LOOKUP[bits]);
+ table.insert(base64,"=");
+ elseif (bitCount == 2) then
+ bits = LSHIFT(bits,4);
+ table.insert(base64,LOOKUP[bits]);
+ table.insert(base64,"==");
+ end
+
+ return table.concat(base64,"");
+end
+
+Base64.fromString = function(string)
+ return Base64.fromArray(Array.fromString(string));
+end
+
+
+
+Base64.toStream = function(base64)
+ return Stream.fromArray(Base64.toArray(base64));
+end
+
+Base64.toArray = function(base64)
+ local bits = 0x00;
+ local bitCount = 0;
+
+ local bytes = {};
+
+ for c in String.gmatch(base64,".") do
+ if (c == "=") then
+ bits = RSHIFT(bits,2); bitCount = bitCount - 2;
+ else
+ bits = LSHIFT(bits,6); bitCount = bitCount + 6;
+ bits = OR(bits,LOOKUP[c]);
+ end
+
+ while(bitCount >= 8) do
+ bitCount = bitCount - 8;
+ local temp = RSHIFT(bits,bitCount);
+ table.insert(bytes,temp);
+ bits = AND(bits,NOT(LSHIFT(0xFFFFFFFF,bitCount)));
+ end
+ end
+
+ return bytes;
+end
+
+Base64.toString = function(base64)
+ local bits = 0x00;
+ local bitCount = 0;
+
+ local chars = {};
+
+ for c in String.gmatch(base64,".") do
+ if (c == "=") then
+ bits = RSHIFT(bits,2); bitCount = bitCount - 2;
+ else
+ bits = LSHIFT(bits,6); bitCount = bitCount + 6;
+ bits = OR(bits,LOOKUP[c]);
+ end
+
+ while(bitCount >= 8) do
+ bitCount = bitCount - 8;
+ local temp = RSHIFT(bits,bitCount);
+ table.insert(chars,String.char(temp));
+ bits = AND(bits,NOT(LSHIFT(0xFFFFFFFF,bitCount)));
+ end
+ end
+
+ return table.concat(chars,"");
+end
+
+return Base64;
diff --git a/gamemode/shared/lockbox/bit.lua b/gamemode/shared/lockbox/bit.lua
new file mode 100644
index 0000000..0ccdb82
--- /dev/null
+++ b/gamemode/shared/lockbox/bit.lua
@@ -0,0 +1,11 @@
+local e = bit
+
+-- Workaround to support Lua 5.2 bit32 API with the LuaJIT bit one
+if e.rol and not e.lrotate then
+ e.lrotate = e.rol
+end
+if e.ror and not e.rrotate then
+ e.rrotate = e.ror
+end
+
+return bit
diff --git a/gamemode/shared/lockbox/ecb.lua b/gamemode/shared/lockbox/ecb.lua
new file mode 100644
index 0000000..67f4514
--- /dev/null
+++ b/gamemode/shared/lockbox/ecb.lua
@@ -0,0 +1,191 @@
+local Array = include("array.lua");
+local Stream = include("stream.lua");
+local Queue = include("queue.lua");
+
+local Bit = include("bit.lua");
+
+local CBC = {};
+
+CBC.Cipher = function()
+
+ local public = {};
+
+ local key;
+ local blockCipher;
+ local padding;
+ local inputQueue;
+ local outputQueue;
+ local iv;
+
+ public.setKey = function(keyBytes)
+ print("Set key to:")
+ print(keyBytes)
+ key = keyBytes;
+ return public;
+ end
+
+ public.setBlockCipher = function(cipher)
+ blockCipher = cipher;
+ return public;
+ end
+
+ public.setPadding = function(paddingMode)
+ padding = paddingMode;
+ return public;
+ end
+
+ public.init = function()
+ inputQueue = Queue();
+ outputQueue = Queue();
+ iv = nil;
+ return public;
+ end
+
+ public.update = function(messageStream)
+ print("Entering update")
+ local byte = messageStream();
+ while (byte ~= nil) do
+ print("processing byte")
+ inputQueue.push(byte);
+ print("inputQueue.size is:" .. inputQueue.size())
+ print("blockCipher.blockSize:" .. blockCipher.blockSize)
+ if(inputQueue.size() >= blockCipher.blockSize) then
+ print("reading from queue")
+ local block = Array.readFromQueue(inputQueue,blockCipher.blockSize);
+ if(iv == nil) then
+ print("iv was nil, iv is now")
+ iv = block;
+ PrintTable(block)
+ else
+ print("iv was not nil, doing thing")
+ local out = Array.XOR(iv,block);
+ print("Calling encrypt with key:")
+ print(key)
+ print("and out")
+ print(out)
+ out = blockCipher.encrypt(key,out);
+ print("Out was:")
+ print(out)
+ Array.writeToQueue(outputQueue,out);
+ iv = out;
+ end
+ end
+ byte = messageStream();
+ end
+ print("Before update returned, blockCipher was ")
+ PrintTable(blockCipher)
+ return public;
+ end
+
+ public.finish = function()
+ paddingStream = padding(blockCipher.blockSize,inputQueue.getHead());
+ public.update(paddingStream);
+
+ return public;
+ end
+
+ public.getOutputQueue = function()
+ return outputQueue;
+ end
+
+ public.asHex = function()
+ print("Outputqueue is:")
+ PrintTable(outputQueue)
+ return Stream.toHex(outputQueue.pop);
+ end
+
+ public.asBytes = function()
+ return Stream.toArray(outputQueue.pop);
+ end
+
+ return public;
+
+end
+
+
+CBC.Decipher = function()
+
+ local public = {};
+
+ local key;
+ local blockCipher;
+ local padding;
+ local inputQueue;
+ local outputQueue;
+ local iv;
+
+ public.setKey = function(keyBytes)
+ key = keyBytes;
+ return public;
+ end
+
+ public.setBlockCipher = function(cipher)
+ blockCipher = cipher;
+ return public;
+ end
+
+ public.setPadding = function(paddingMode)
+ padding = paddingMode;
+ return public;
+ end
+
+ public.init = function()
+ inputQueue = Queue();
+ outputQueue = Queue();
+ iv = nil;
+ return public;
+ end
+
+ public.update = function(messageStream)
+ print("Updateing decipher with messagestream")
+ local byte = messageStream();
+ while (byte ~= nil) do
+ inputQueue.push(byte);
+ if(inputQueue.size() >= blockCipher.blockSize) then
+ local block = Array.readFromQueue(inputQueue,blockCipher.blockSize);
+
+ if(iv == nil) then
+ iv = block;
+ print("Setting iv to ")
+ PrintTable(iv)
+ else
+ local out = block;
+ out = blockCipher.decrypt(key,out);
+ out = Array.XOR(iv,out);
+ Array.writeToQueue(outputQueue,out);
+ iv = block;
+ end
+ end
+ byte = messageStream();
+ end
+ return public;
+ end
+
+ public.finish = function()
+ paddingStream = padding(blockCipher.blockSize,inputQueue.getHead());
+ public.update(paddingStream);
+
+ return public;
+ end
+
+ public.getOutputQueue = function()
+ return outputQueue;
+ end
+
+ public.asHex = function()
+ return Stream.toHex(outputQueue.pop);
+ end
+
+ public.asBytes = function()
+ return Stream.toArray(outputQueue.pop);
+ end
+
+ public.asString = function()
+ return Stream.toString(outputQueue.pop)
+ end
+
+ return public;
+
+end
+
+return CBC;
diff --git a/gamemode/shared/lockbox/padding.lua b/gamemode/shared/lockbox/padding.lua
new file mode 100644
index 0000000..72be077
--- /dev/null
+++ b/gamemode/shared/lockbox/padding.lua
@@ -0,0 +1,21 @@
+local Stream = include("stream.lua");
+
+local ZeroPadding = function(blockSize,byteCount)
+
+ local paddingCount = blockSize - ((byteCount -1) % blockSize) + 1;
+ local bytesLeft = paddingCount;
+
+ local stream = function()
+ if bytesLeft > 0 then
+ bytesLeft = bytesLeft - 1;
+ return 0x00;
+ else
+ return nil;
+ end
+ end
+
+ return stream;
+
+end
+
+return ZeroPadding;
diff --git a/gamemode/shared/lockbox/queue.lua b/gamemode/shared/lockbox/queue.lua
new file mode 100644
index 0000000..55b067d
--- /dev/null
+++ b/gamemode/shared/lockbox/queue.lua
@@ -0,0 +1,47 @@
+local Queue = function()
+ local queue = {};
+ local tail = 0;
+ local head = 0;
+
+ local public = {};
+
+ public.push = function(obj)
+ queue[head] = obj;
+ head = head + 1;
+ return;
+ end
+
+ public.pop = function()
+ if tail < head
+ then
+ local obj = queue[tail];
+ queue[tail] = nil;
+ tail = tail + 1;
+ return obj;
+ else
+ return nil;
+ end
+ end
+
+ public.size = function()
+ return head - tail;
+ end
+
+ public.getHead = function()
+ return head;
+ end
+
+ public.getTail = function()
+ return tail;
+ end
+
+ public.reset = function()
+ queue = {};
+ head = 0;
+ tail = 0;
+ end
+
+ return public;
+end
+
+return Queue;
diff --git a/gamemode/shared/lockbox/stream.lua b/gamemode/shared/lockbox/stream.lua
new file mode 100644
index 0000000..aeb3b18
--- /dev/null
+++ b/gamemode/shared/lockbox/stream.lua
@@ -0,0 +1,112 @@
+local Queue = include("queue.lua");
+local String = string
+
+local Stream = {};
+
+
+Stream.fromString = function(string)
+ local i=0;
+ return function()
+ print("string is:" .. string)
+ print("len is:" .. string.len(string))
+ print("i is:" .. i)
+ i=i+1;
+ if(i <= string.len(string)) then
+ return string.byte(string,i);
+ else
+ return nil;
+ end
+ end
+end
+
+
+Stream.toString = function(stream)
+ local array = {};
+ local i=1;
+
+ local byte = stream();
+ while byte ~= nil do
+ array[i] = String.char(byte);
+ i = i+1;
+ byte = stream();
+ end
+
+ return table.concat(array,"");
+end
+
+
+Stream.fromArray = function(array)
+ local queue = Queue();
+ local i=1;
+
+ local byte = array[i];
+ while byte ~= nil do
+ queue.push(byte);
+ i=i+1;
+ byte = array[i];
+ end
+
+ return queue.pop;
+end
+
+
+Stream.toArray = function(stream)
+ local array = {};
+ local i=1;
+
+ local byte = stream();
+ while byte ~= nil do
+ array[i] = byte;
+ i = i+1;
+ byte = stream();
+ end
+
+ return array;
+end
+
+
+local fromHexTable = {};
+for i=0,255 do
+ fromHexTable[String.format("%02X",i)]=i;
+ fromHexTable[String.format("%02x",i)]=i;
+end
+
+Stream.fromHex = function(hex)
+ local queue = Queue();
+
+ for i=1,String.len(hex)/2 do
+ local h = String.sub(hex,i*2-1,i*2);
+ queue.push(fromHexTable[h]);
+ end
+
+ return queue.pop;
+end
+
+
+
+local toHexTable = {};
+for i=0,255 do
+ toHexTable[i]=String.format("%02X",i);
+end
+
+Stream.toHex = function(stream)
+ print("tohex called with stream")
+ print(stream)
+ local hex = {};
+ local i = 1;
+
+ local byte = stream();
+ print("First byte is")
+ print(byte)
+ while byte ~= nil do
+ print("Createing hex:")
+ print(table.concat(hex,""))
+ hex[i] = toHexTable[byte];
+ i=i+1;
+ byte = stream();
+ end
+
+ return table.concat(hex,"");
+end
+
+return Stream;
diff --git a/gamemode/shared/sh_setup.lua b/gamemode/shared/sh_setup.lua
new file mode 100644
index 0000000..9c44e57
--- /dev/null
+++ b/gamemode/shared/sh_setup.lua
@@ -0,0 +1,165 @@
+--[[
+ Some values that need to be setup by the server owner
+]]
+
+local aes = include("aes.lua")
+local ECBMode = include("lockbox/ecb.lua")
+local ZeroPadding = include("lockbox/padding.lua")
+local Array = include("lockbox/array.lua")
+local Stream = include("lockbox/stream.lua")
+print("sh_setup included aes successfully")
+
+local valuesneeded = {
+ ["mysql DB host"] = "String",
+ ["mysql DB dbname"] = "String",
+ ["mysql DB uname"] = "String",
+ ["mysql DB pass"] = "String",
+ ["mysql should encrypt pass"] = "Bool",
+ ["mysql encrypt password"] = "String",
+ ["world default server ip:port"] = "String",
+}
+
+ART.Config = ART.Config or {}
+
+if SERVER then
+ util.AddNetworkString( "ART_CONFIG_WRITE" )
+ local function ReadConfig(encryptkey)
+ encryptkey = encryptkey or ""
+ local ftext = file.Read("artery/config.txt", "DATA")
+ if ftext == nil then
+ print("Failed to read Config file, if this is a new setup, use art_setup to get started.")
+ return
+ end
+ local tbl = string.Explode("\n",ftext,false)
+ local strtbl = {}
+ for k,v in pairs(tbl) do
+ local ltext = v:Explode(":",false)
+ strtbl[ltext[1]] = ltext[2]
+ end
+ for k,v in pairs(valuesneeded) do
+ local tfunc = "to" .. v:lower()
+ ART.Config[k] = _G[tfunc](strtbl[k])
+ end
+ if ART.Config["mysql should encrypt pass"] then
+ if encryptkey == "" then
+ print("Failed to retrive MySQL database password, please enter it with the \"artery_dbpasswordkey\" command.")
+ return
+ end
+ ART.Config["mysql DB pass"] = aes.decrypt(lockstream.fromString(encryptkey),lockstream.fromString(ART.Config["mysql DB pass"]))
+ end
+ end
+
+ ReadConfig()
+
+ net.Receive( "ART_CONFIG_MYSQLPASS", function(len,ply)
+ if not ply:IsAdmin() then
+ return
+ end
+ end)
+
+ net.Receive( "ART_CONFIG_WRITE", function(len,ply)
+ print("Received write signal")
+ if not ply:IsAdmin() then return end
+ print("You're an admin!")
+ for k,v in pairs(valuesneeded) do
+ local ftype = "Read" .. v
+ ART.Config[k] = net[ftype]()
+ end
+ if ART.Config["mysql should encrypt pass"] then
+ local key = ART.Config["mysql encrypt password"]
+ local block = ART.Config["mysql DB pass"]
+ local akey = Array.fromString(key)
+ local ablock = Array.fromString(block)
+ local skey = Stream.fromString(key)
+ local sblock = Stream.fromString(block)
+ --print("sblock:" .. sblock)
+ --print("skey:" .. skey)
+ local cipher = ECBMode.Cipher().setKey(akey).setBlockCipher(aes).setPadding(ZeroPadding)
+ local ciphertxt = cipher.init().update(sblock).finish().asHex()
+ local decipher = ECBMode.Decipher().setKey(akey).setBlockCipher(aes).setPadding(ZeroPadding)
+ local deciphertxt = decipher.init().update(Stream.fromHex(ciphertxt)).finish().asHex()
+ print("Cyphertext of " .. block .. " is " .. ciphertxt)
+ print("Deciphertext of " .. ciphertxt .. " is " .. deciphertxt)
+ ART.Config["mysql DB pass"] = ciphertxt
+ end
+ local ftext = {}
+ for k,v in pairs(ART.Config) do
+ ftext[#ftext + 1] = k .. "=" .. tostring(v)
+ end
+ local wtext = table.concat(ftext,"\n")
+ print("Writeing:" .. wtext)
+ file.Write("artery/config.txt",wtext)
+ end)
+
+ net.Receive( "ART_CONFIG_REQUEST", function(len,ply)
+ if not ply:IsAdmin() then return end
+ for k,v in pairs(valuesneeded) do
+ local ftype = "Write" .. v
+ print("Calling " .. ftype .. " on " .. tostring(tbl[k]))
+ net[ftype](tbl[k])
+ end
+ end)
+end
+
+print("Got to before concommands were added")
+
+concommand.Add("artery_dbpasswordkey",function()
+ if CLIENT then return end
+
+end, nil, "Sets the encryption key for the mysql database password")
+
+if CLIENT then
+ print("Got to before setup command")
+
+ concommand.Add("artery_setup", function(ply,cmd,args)
+ print("setup called")
+ if SERVER then return end
+ print("Got past server gaurd")
+ local width = ScrW()
+ local height = ScrH()
+ local configpanel = vgui.Create( "DFrame" )
+ configpanel:SetPos( 0, height/8 )
+ configpanel:SetSize( width/4, (height/4)*3 )
+ configpanel:SetTitle( "Artery Settings" )
+ configpanel:SetDraggable( true )
+ configpanel:MakePopup()
+ local scrollpanel = vgui.Create( "DScrollPanel", configpanel )
+ scrollpanel:Dock(FILL)
+ local entries = {}
+ for k,v in pairs(valuesneeded) do
+ local settinglabel = vgui.Create( "DLabel", scrollpanel )
+ settinglabel:Dock(TOP)
+ settinglabel:SetText( k )
+ scrollpanel:AddItem(settinglabel)
+ local settingentry
+ if v == "String" then
+ settingentry = vgui.Create( "DTextEntry", scrollpanel )
+ settingentry:SetSize(width/10,18)
+ settingentry:Dock(TOP)
+ elseif v == "Bool" then
+ settingentry = vgui.Create( "DCheckBox", holder)
+ settingentry:Dock(TOP)
+ --settingentry:SetSize(18,18)
+ end
+ scrollpanel:AddItem(settingentry)
+ entries[k] = settingentry
+ end
+ local savebutton = vgui.Create( "DButton",scrollpanel )
+ savebutton.DoClick = function()
+ net.Start( "ART_CONFIG_WRITE")
+ for k,v in pairs(valuesneeded) do
+ local nfunc = "Write"..v
+ local value = nil
+ if v == "String" then value = entries[k]:GetValue()
+ elseif v == "Bool" then value = entries[k]:GetChecked() end
+ assert(value ~= nil, "Didn't know setting type:" .. v .. " for " .. k)
+ print("Doing " .. nfunc .. " on " .. tostring(value))
+ net[nfunc](value)
+ end
+ net.SendToServer()
+ end
+ savebutton:SetText("Save config")
+ savebutton:Dock(TOP)
+ scrollpanel:AddItem(savebutton)
+ end)
+end
diff --git a/gamemode/shared/sparkel.lua b/gamemode/shared/sparkel.lua
new file mode 100644
index 0000000..5882aac
--- /dev/null
+++ b/gamemode/shared/sparkel.lua
@@ -0,0 +1,17 @@
+
+function sparkel(...)
+ local arg = {...}
+ local looparg = type(arg[1]) == "string" and string.Explode(" ",arg[1],false) or arg
+ --One pass to find the high and low point
+ local max,min = tonumber(looparg[1]),tonumber(looparg[1])
+ for k,v in pairs(looparg) do
+ v = tonumber(v)
+ max = max > v and max or v
+ min = min < v and min or v
+ end
+ local scale = (max-min)/7
+ for k,v in pairs(looparg) do
+ Msg(utf8.char(9600+(1+(v/scale))))
+ end
+ Msg("\n")
+end