Login
Register
Menu
Home
Forum
JassDoc
Types
Functions
Variables
Help
Chat
Media
Search
Search posts
WC3 JASS.com
"The Jass Vault" plus vJASS and Zinc
WC3 Modding Information Center
Forum
Warcraft (WC3) Modding
Warcraft III Resources
Warcraft III Spells and Systems
Codes & Snippets
Faux HandleVars & CSCache
Warcraft III:
Maps
Models
Skins
Icons
Spells / Systems
Tools
Tutorials
Snippets
JASS vJASS Spells and Systems
Tutorials
Chat @Discord
vJASS & Zinc Documentation
For the latest documentation about how it works vJASS and Zinc language layers for Warcraft III, please follow these links:
Jasshelper documentation
-
Zinc documentation
-
WC3 Optimizer documentation
Faux HandleVars & CSCache
Codes & Snippets
Started by
moyack
Views
2058
Replies
0
Users
1
1
Pages:
1
Go Down
0 Members and 1 Guest are viewing this topic.
Vexorian
Recognized User
Posts:
5
WC3 Models: 0
WC3 Tutorials: 0
WC3 Tools: 0
WC3 Maps: 0
WC3 Skins: 0
WC3 Icons: 0
WC3 Spells: 0
Reputation:
100
Free Software Terrorist
Faux HandleVars & CSCache
on:
December 09, 2010, 09:01:10 AM
Category:
Execution, Variables
Language:
vJASS
Download Demo Map
This is the closest you could reproduce Handle Vars' functionality and interface in (currently westfall) patch 1.24, requires jasshelper 0.9.H.2 and patch 1.24 or later.
Are intended so implementing these handle vars in your map should be able to replace Handle Vars functionality, however, in some odd cases in which you do very odd stuff it won't work (will raise compiler errors), those cases should be rare.
Faux Handle Vars do not have the I2H-related issues that plagued original handle vars, should also be mildly faster (I still recommend AgentVars for a better speed improvement, or even better, structs). However, I do not recommend these functions for anything other than porting old code to patch 1.24. It is because this interface is very leak-friendly (these leaks are also very common in code that uses handle vars, and are almost by-design) Although the leaks weren't a big issue for most maps using Handle vars (not even DOTA) they are still undesirable...
Faux CSCache works the same, except in some cases they might not work 100% well because of how in CSCache you were allowed to use inline gamecache calls and other retardedness... do notice that Faux CSCache will leak memory like ... well, like something that leaks a lot of memory...
CSCache has worked to make spell factory and also some other spell maps work again (once you also move CS to 16.0)
Due to blizzard's failed failedness, You may find some cases like:
Code: jass
call
AttachObject( meh,
"..."
, #TriggerAddAction(t,
function
ff)# )
These lines will cause a syntax error, why? Because blizzard for some INCREDIBLY STUPID reason didn't make
triggeraction
extend
agent
in common.j
The fix for that would be something like:
Code: jass
call
AttachObject( meh,
"..."
,
null
)
call
TriggerAddAction
(t,
function
ff)
Differences between these handle vars and the original ones
They are called handle vars and have function names like SetHandleHandle just for the reason of compatibility, in reality, you can only use these functions to attach stuff to objects of the
agent
type. SetHandleHandle is only able to attach agents. I.E you cannot use SetHandleHandle to attach a lightning effect, would have to use SetHandleLightning instead) Since GetHandleHandle is basically impossible (even one that returns agent) it has been removed.
Faux Handle Vars
Code: jass
/*******************************************************************************************
Faux Handle Vars
----------------
Do not use these functions for new stuff, it is just not the right thing to do...
The intention of Faux Handle Vars is to be a patch fix for a map's migration to
patch 1.24 This library might not cover all uses of handle vars, some of them are just
impossible with the new rules set in patches 1.23b and 1.24, but they should work for
most of the cases....
All of them but the SetHandle*** ones are inline friendly. I follow the interface
in official Kattana's handle vars from wc3jass.com, if your handle vars functions
look different, then you were not using handle vars but another thing...
*******************************************************************************************/
//==========================================================================================
library
HandleVars
initializer
init
globals
private
hashtable
ht
endglobals
// too bad the Handle vars' old functionality forces me to make these things
// inline-unfriendly
function
SetHandleHandle
takes
agent
subject,
string
label,
agent
value
returns
nothing
if
(value==
null
)
then
call
RemoveSavedHandle
( ht,
GetHandleId
(subject),
StringHash
(label))
else
call
SaveAgentHandle
( ht,
GetHandleId
(subject),
StringHash
(label), value)
endif
endfunction
function
SetHandleInt
takes
agent
subject,
string
label,
integer
value
returns
nothing
if
value==0
then
call
RemoveSavedInteger
(ht,
GetHandleId
(subject),
StringHash
(label))
else
call
SaveInteger
(ht,
GetHandleId
(subject),
StringHash
(label), value)
endif
endfunction
function
SetHandleBoolean
takes
agent
subject,
string
label,
boolean
value
returns
nothing
if
(value ==
false
)
then
call
RemoveSavedBoolean
(ht,
GetHandleId
(subject),
StringHash
(label))
else
call
SaveBoolean
(ht,
GetHandleId
(subject),
StringHash
(label), value)
endif
endfunction
function
SetHandleReal
takes
agent
subject,
string
label,
real
value
returns
nothing
if
(value == 0.0)
then
call
RemoveSavedReal
(ht,
GetHandleId
(subject),
StringHash
(label))
else
call
SaveReal
(ht,
GetHandleId
(subject),
StringHash
(label), value)
endif
endfunction
function
SetHandleString
takes
agent
subject,
string
label,
string
value
returns
nothing
if
((value==
""
)
or
(value==
null
))
then
call
RemoveSavedString
(ht,
GetHandleId
(subject),
StringHash
(label))
else
call
SaveStr
(ht,
GetHandleId
(subject),
StringHash
(label), value)
//yay for blizz' consistent naming scheme...
endif
endfunction
function
GetHandleHandle
takes
agent
subject,
string
label
returns
agent
debug
call
BJDebugMsg
(
"[debug] What the heck? Why would you call HandleHandle I guess this was caused by a search and replace mistake"
)
return
null
endfunction
// these are inline friendly, ok, maybe they aren't because jasshelper does not recognize
// GetHandleId as non-state changing. But they will be once I fix jasshelper...
function
GetHandleInt
takes
agent
subject,
string
label
returns
integer
return
LoadInteger
(ht,
GetHandleId
(subject),
StringHash
(label))
endfunction
function
GetHandleBoolean
takes
agent
subject,
string
label
returns
boolean
return
LoadBoolean
(ht,
GetHandleId
(subject),
StringHash
(label))
endfunction
function
GetHandleString
takes
agent
subject,
string
label
returns
string
return
LoadStr
(ht,
GetHandleId
(subject),
StringHash
(label))
endfunction
function
GetHandleReal
takes
agent
subject,
string
label
returns
real
return
LoadReal
(ht,
GetHandleId
(subject),
StringHash
(label))
endfunction
// got bored so I now use a textmacro...
//! textmacro FAUX_HANDLE_VARS_GetHandleHandle takes NAME, TYPE
function
SetHandle$NAME$
takes
agent
subject,
string
label, $TYPE$ value
returns
nothing
if
(value==
null
)
then
call
RemoveSavedHandle
( ht,
GetHandleId
(subject),
StringHash
(label))
else
call
Save$NAME$Handle( ht,
GetHandleId
(subject),
StringHash
(label), value)
endif
endfunction
function
GetHandle$NAME$
takes
agent
subject,
string
label
returns
$TYPE$
return
Load$NAME$Handle( ht,
GetHandleId
(subject),
StringHash
(label))
endfunction
//! endtextmacro
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Player","player")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Widget","widget")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Destructable","destructable")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Item","item")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Unit","unit")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Ability","ability")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Timer","timer")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Trigger","trigger")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TriggerCondition","triggercondition")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TriggerAction","triggeraction")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TriggerEvent","event")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Force","force")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Group","group")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Location","location")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Rect","rect")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("BooleanExpr","boolexpr")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Sound","sound")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Effect","effect")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("UnitPool","unitpool")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("ItemPool","itempool")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Quest","quest")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("QuestItem","questitem")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("DefeatCondition","defeatcondition")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TimerDialog","timerdialog")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Leaderboard","leaderboard")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Multiboard","multiboard")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("MultiboardItem","multiboarditem")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Trackable","trackable")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Dialog","dialog")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Button","button")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TextTag","texttag")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Lightning","lightning")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Image","image")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Ubersplat","ubersplat")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Region","region")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("FogState","fogstate")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("FogModifier","fogmodifier")
//! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Hashtable","hashtable")
function
FlushHandleVars
takes
agent
subject
returns
nothing
call
FlushChildHashtable
(ht,
GetHandleId
(subject))
endfunction
function
FlushHandleLocals
takes
agent
subject
returns
nothing
call
FlushHandleVars(subject)
endfunction
private
function
init
takes
nothing
returns
nothing
set
ht=
InitHashtable
()
endfunction
endlibrary
Faux CSCache
Code: jass
/*******************************************************************************************
Faux CSCache AttachVars
----------------
Do not use these functions for new stuff, it is just not the right thing to do...
The intention of Faux CSCache is to be a patch fix for a map's migration to
patch 1.24 This library might not cover all uses of handle vars, some of them are just
impossible with the new rules set in patches 1.23b and 1.24, but they should work for
most of the cases....
*******************************************************************************************/
//==========================================================================================
library
CSCache
initializer
init
requires
CSSafeCache
globals
private
hashtable
ht
endglobals
// too bad the Handle vars' old functionality forces me to make these things
// inline-unfriendly
function
SetTableObject
takes
string
subject,
string
label,
agent
value
returns
nothing
if
(value==
null
)
then
call
RemoveSavedHandle
( ht,
StringHash
(subject),
StringHash
(label))
else
call
SaveAgentHandle
( ht,
StringHash
(subject),
StringHash
(label), value)
endif
endfunction
function
GetTableHandle
takes
string
subject,
string
label
returns
agent
debug
call
BJDebugMsg
(
"[debug] What the heck? Why would you call HandleHandle I guess this was caused by a search and replace mistake"
)
return
null
endfunction
// these are inline friendly, ok, maybe they aren't because jasshelper does not recognize
// GetHandleId as non-state changing. But they will be once I fix jasshelper...
// got bored so I now use a textmacro...
//! textmacro FAUX_HANDLE_VARS_GetTableHandle takes NAME, TYPE
function
SetTable$NAME$
takes
string
subject,
string
label, $TYPE$ value
returns
nothing
if
(value==
null
)
then
call
RemoveSavedHandle
( ht,
StringHash
(subject),
StringHash
(label))
else
call
Save$NAME$Handle( ht,
StringHash
(subject),
StringHash
(label), value)
endif
endfunction
function
GetTable$NAME$
takes
string
subject,
string
label
returns
$TYPE$
return
Load$NAME$Handle( ht,
StringHash
(subject),
StringHash
(label))
endfunction
//! endtextmacro
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Player","player")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Widget","widget")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Destructable","destructable")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Item","item")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Unit","unit")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Ability","ability")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Timer","timer")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Trigger","trigger")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TriggerCondition","triggercondition")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TriggerAction","triggeraction")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TriggerEvent","event")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Force","force")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Group","group")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Location","location")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Rect","rect")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("BooleanExpr","boolexpr")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Sound","sound")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Effect","effect")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("UnitPool","unitpool")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("ItemPool","itempool")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Quest","quest")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("QuestItem","questitem")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("DefeatCondition","defeatcondition")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TimerDialog","timerdialog")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Leaderboard","leaderboard")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Multiboard","multiboard")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("MultiboardItem","multiboarditem")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Trackable","trackable")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Dialog","dialog")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Button","button")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TextTag","texttag")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Lightning","lightning")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Image","image")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Ubersplat","ubersplat")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Region","region")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("FogState","fogstate")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("FogModifier","fogmodifier")
//! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Hashtable","hashtable")
function
CS_KillTrigger
takes
trigger
t
returns
nothing
// let em leak
endfunction
// too bad the Handle vars' old functionality forces me to make these things
// inline-unfriendly
function
AttachObject
takes
agent
subject,
string
label,
agent
value
returns
nothing
call
SetTableObject( GetAttachmentTable(subject) , label, value)
endfunction
function
GetAttachedHandle
takes
agent
subject,
string
label
returns
agent
debug
call
BJDebugMsg
(
"[debug] What the heck? Why would you call HandleHandle I guess this was caused by a search and replace mistake"
)
return
null
endfunction
// these are inline friendly, ok, maybe they aren't because jasshelper does not recognize
// GetHandleId as non-state changing. But they will be once I fix jasshelper...
// got bored so I now use a textmacro...
//! textmacro FAUX_HANDLE_VARS_GetAttachedHandle takes NAME, TYPE
function
Attach$NAME$
takes
agent
subject,
string
label, $TYPE$ value
returns
nothing
call
SetTable$NAME$( GetAttachmentTable(subject), label, value)
endfunction
function
GetAttached$NAME$
takes
agent
subject,
string
label
returns
$TYPE$
return
GetTable$NAME$( GetAttachmentTable(subject), label)
endfunction
//! endtextmacro
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Player","player")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Widget","widget")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Destructable","destructable")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Item","item")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Unit","unit")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Ability","ability")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Timer","timer")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Trigger","trigger")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TriggerCondition","triggercondition")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TriggerAction","triggeraction")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TriggerEvent","event")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Force","force")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Group","group")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Location","location")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Rect","rect")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("BooleanExpr","boolexpr")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Sound","sound")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Effect","effect")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("UnitPool","unitpool")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("ItemPool","itempool")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Quest","quest")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("QuestItem","questitem")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("DefeatCondition","defeatcondition")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TimerDialog","timerdialog")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Leaderboard","leaderboard")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Multiboard","multiboard")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("MultiboardItem","multiboarditem")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Trackable","trackable")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Dialog","dialog")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Button","button")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TextTag","texttag")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Lightning","lightning")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Image","image")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Ubersplat","ubersplat")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Region","region")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("FogState","fogstate")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("FogModifier","fogmodifier")
//! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Hashtable","hashtable")
private
function
init
takes
nothing
returns
nothing
set
ht=
InitHashtable
()
endfunction
endlibrary
Pyrogasm recommendations
For anyone attempting to use the Faux CSCache system:
You will need two additional libraries from Vex's original CasterSystem. They are CSSafeCache and CSData. Their code is below and all 3 libraries are in the attached map to show how they should be implemented.
CSData
Code: jass
library
CSData
initializer
init
//****************************************************************************************************
// CSData 16.0
// ¯¯¯¯¯¯¯¯¯¯¯
// CSDatas are like UserData in units and items, they now use a hashtable instead of big arrays,
// should be faster and safer
//
// Notice that for public spells or systems to be distributed you should only use these
// for private objects (those who the mapper would never have access to) If you are making something
// for your map you can use them wherever you want.
//
// Best to be used in conjunction to CSArrays so you just specify an array id for a handle.
//
// DO NOT USE THIS ON THESE HANDLE TYPES: -lightning, -ubersplat, -image, -texttag,
// -any 'argument' handle (like playerstate, damagetype, etc)
//
//****************************************************************************************************
//====================================================================================================
globals
private
constant
integer
MAX_HANDLE_ID_COUNT = 408000
// values lower than 8191: very fast, but very unsafe.
// values bigger than 8191: not that fast, the bigger the number is the slower the function gets
// Most maps don't really need a value bigger than 50000 here, but if you are unsure, leave it
// as the rather inflated value of 408000
endglobals
//=================================================================================================
// a.k.a H2I, changed name to CS_H2I to prevent conflicts with other systems, it then stayed that
// instead of changing to a private or public function since many outside spells use it.
//
function
CS_H2I
takes
handle
h
returns
integer
//For compat
return
GetHandleId
(h)
//
endfunction
//
//==================================================================================================
globals
private
hashtable
ht
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function
SetCSData
takes
handle
h,
integer
v
returns
nothing
call
SaveInteger
(ht , 0,
GetHandleId
(h) , v)
endfunction
function
GetCSData
takes
handle
h
returns
integer
return
LoadInteger
( ht, 0,
GetHandleId
(h) )
endfunction
private
function
init
takes
nothing
returns
nothing
set
ht =
InitHashtable
()
endfunction
endlibrary
CSSafeCache
Code: jass
library
CSSafeCache
initializer
init
requires
CSData
//*************************************************************************************************
//* *
//* CSSafeCache 15.3 [url]http://wc3campaigns.net/vexorian[/url] *
//* ¯¯¯¯¯¯¯ *
//* CSCache is evil now, use just CSSafeCache when possible as it now contains all functions *
//* that do not use I2H or similar functions that are considered to cause unstability in the map *
//* *
//* CSCache has been deprecated, and is now unusuable since it can't be ported to patch 1.23b *
//* Migration from CSCache to CSSafeCache+structs should be easy *
//* *
//* However, for old compatibility, CSSafeCache needs to stick to using gamecache, which is not *
//* as good as hashtable (it is slower and may be vulnerable to Sync attacks) I recommend *
//* switching from CSSafeCache to hashtable or Table *
//* *
//*************************************************************************************************
//=================================================================================================
// CSSafeCache globals:
//
globals
gamecache
cs_cache =
null
integer
array
cs_array1
integer
array
cs_array3
integer
array
cs_array2
private
integer
array
cs_freeindexes
private
integer
array
cs_pairx
private
integer
array
cs_pairy
private
integer
array
cs_freepairs
endglobals
private
function
init
takes
nothing
returns
nothing
// CSSafeCache initializer :
call
FlushGameCache
(
InitGameCache
(
"cscache"
))
set
cs_cache=
InitGameCache
(
"cscache"
)
call
ExecuteFunc
(
"InitArrayIndexes"
)
call
ExecuteFunc
(
"Pool_SetupCharMap"
)
endfunction
//=================================================================================================================
// CS Pairs
// ¯¯¯¯¯¯¯¯
// This is a sub system to assist csarrays, you can use them but CSArrays of size 2 have the same functionality
// although cspairs are be faster their space is limited and will start using gamecache if abused
//
function
NewPair
takes
integer
x,
integer
y
returns
integer
local
integer
i
if
(cs_freepairs[0]==0)
then
set
cs_freepairs[8190]=cs_freepairs[8190]+1
set
i= cs_freepairs[8190]
else
set
i= cs_freepairs[cs_freepairs[0]]
set
cs_freepairs[0]=cs_freepairs[0]-1
endif
if
(i>=8189)
then
//because we can only recycle up to 8189 (free pairs array uses indexes 0 and 8190 for other purposes)
call
StoreInteger
(cs_cache,
"pairx"
,
I2S
(i),x)
call
StoreInteger
(cs_cache,
"pairy"
,
I2S
(i),y)
else
set
cs_pairx[i]=x
set
cs_pairy[i]=y
endif
return
i
endfunction
function
DestroyPair
takes
integer
id
returns
nothing
if
(id>=8189)
then
call
FlushStoredInteger
(cs_cache,
"pairx"
,
I2S
(id))
call
FlushStoredInteger
(cs_cache,
"pairy"
,
I2S
(id))
else
set
cs_freepairs[0]=cs_freepairs[0]+1
set
cs_freepairs[cs_freepairs[0]] = id
endif
endfunction
function
SetPairXY
takes
integer
id,
integer
x,
integer
y
returns
nothing
if
(id>=8189)
then
call
StoreInteger
(cs_cache,
"pairx"
,
I2S
(id),x)
call
StoreInteger
(cs_cache,
"pairy"
,
I2S
(id),y)
else
set
cs_pairx[id]=x
set
cs_pairy[id]=y
endif
endfunction
function
SetPairX
takes
integer
id,
integer
x
returns
nothing
if
(id>=8189)
then
call
StoreInteger
(cs_cache,
"pairx"
,
I2S
(id),x)
else
set
cs_pairx[id]=x
endif
endfunction
function
SetPairY
takes
integer
id,
integer
y
returns
nothing
if
(id>=8189)
then
call
StoreInteger
(cs_cache,
"pairy"
,
I2S
(id),y)
else
set
cs_pairy[id]=y
endif
endfunction
function
GetPairX
takes
integer
id
returns
integer
if
(id>=8189)
then
return
GetStoredInteger
(cs_cache,
"pairy"
,
I2S
(id))
endif
return
cs_pairx[id]
endfunction
function
GetPairY
takes
integer
id
returns
integer
if
(id>=8189)
then
return
GetStoredInteger
(cs_cache,
"pairx"
,
I2S
(id))
endif
return
cs_pairy[id]
endfunction
//=================================================================================================================
// CS Dynamic Arrays
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Thanks: Pipedream, Peppar
//
// We can now create arrays in game! , also pass them as arguments or return values!
// a 1 length array is a pointer!
//
function
Array_TryFree
takes
nothing
returns
nothing
local
integer
i
local
integer
N=cs_array1[0]
local
integer
k
local
boolean
cleaned=
false
local
integer
loc
local
integer
q
local
integer
r
set
i=cs_array1[146]
if
(i>144)
then
call
TimerStart
(
GetExpiredTimer
(),60.,
false
,
function
Array_TryFree)
return
endif
set
loc=cs_freeindexes[i]
set
q=0
loop
exitwhen
(loc==0)
// we could just have used:
//set k=GetPairX(loc)
//set r=GetPairY(loc) But it is slower than direct usage:
if
(loc>=8192)
then
set
k=
GetStoredInteger
(cs_cache,
"pairx"
,
I2S
(loc))
set
r=
GetStoredInteger
(cs_cache,
"pairy"
,
I2S
(loc))
else
set
k=cs_pairx[loc]
set
r=cs_pairy[loc]
endif
if
(k+i-1==N)
then
//we found one we can remove from the list
set
cleaned=
true
//decrement N
set
N=k-2
//Remove from the list:
if
(q==
null
)
then
//That was the first, update the array as well
set
cs_freeindexes[i]=r
else
//Update the next of the previous one
//We could use : call SetPairY(q,,r) but it is slower
if
(q>=8189)
then
call
StoreInteger
(cs_cache,
"pairy"
,
I2S
(q),r)
else
set
cs_pairy[q]=r
endif
endif
if
(r==
null
)
then
//This was the last one, update it in the array as well
set
cs_freeindexes[i+4096]=q
endif
call
DestroyPair(loc)
set
loc=q
endif
set
q=loc
set
loc=r
endloop
if
(cleaned)
then
set
cs_array1[0]=N
set
cs_array1[146]=1
else
set
cs_array1[146]=cs_array1[i+1]
endif
call
TimerStart
(
GetExpiredTimer
(),0.2,
false
,
function
Array_TryFree)
endfunction
function
InitArrayIndexes2
takes
nothing
returns
nothing
local
integer
i=0
loop
exitwhen
(i==8191)
set
cs_pairx[i]=777
set
cs_pairy[i]=777
set
i=i+1
endloop
endfunction
function
InitArrayIndexes
takes
nothing
returns
nothing
local
integer
i=0
local
integer
a=1
local
integer
b=1
local
integer
c
//By placing 777 there instead of 0 it is easier to recognize non correctly initialized bugs
loop
exitwhen
(i== 8191)
set
cs_array1[i]=777
set
cs_array2[i]=777
set
cs_array3[i]=777
//set cs_pairx[i]=777
//set cs_pairy[i]=777
set
i=i+1
endloop
call
ExecuteFunc
(
"InitArrayIndexes2"
)
set
cs_freeindexes[0]=0
//The stack for the table indexes.
set
cs_freepairs[0]=0
set
cs_freepairs[8190]=0
set
i=1
loop
set
c=a+b
set
a=b
set
b=c
exitwhen
(b>144)
//max size is 144
set
cs_freeindexes[b]=0
//the first of the list
set
cs_freeindexes[b+4096]=0
//the last of the list
loop
exitwhen
(i>b)
set
cs_array1[i]=b
set
i=i+1
endloop
endloop
set
cs_array1[i]=b
//i is 145
set
cs_array1[146]=1
set
cs_array1[147]=101
//initial table index is 101
set
cs_array1[0]=147
//index 0: Last used index
// 1 to 145 : Fibonacci sequence
// 146 : last check
// 147 : Table indexes check
//This has a good chance to compress the thing when necesary
call
TimerStart
(
CreateTimer
(),60.,
false
,
function
Array_TryFree)
endfunction
//=============================================================================================
// Create an array of size, max size is 144, if doinit is true it will put a bunch of zeros
// in the indexes
//
function
NewArray
takes
integer
size,
boolean
doinit
returns
integer
local
integer
i
local
integer
rsize=cs_array1[size]
local
integer
loc
set
loc=cs_freeindexes[rsize]
if
(loc!=0)
then
set
cs_freeindexes[rsize]= GetPairY(loc)
if
(cs_freeindexes[rsize]==0)
then
set
cs_freeindexes[4096+rsize]=0
endif
set
i=GetPairX(loc)
call
DestroyPair(loc)
if
(i==0)
then
//this code was probably a good idea when we used locations for the free indexes list, now we use pairs which should not ever
//do this unless someone modiffied the pair array incorrectly
call
BJDebugMsg
(
"Caster System: Unexpected error (5): corrupt stack, attempt to recover "
+
I2S
(rsize))
// recovering involves forgetting about the stack which got corrupted and start again from zero, it will leak
// and probably get slow due to usage of gamecache but it is better than the problems that a corrupt stack might cause
set
cs_freeindexes[rsize]=0
set
cs_freeindexes[4096+rsize]=0
return
NewArray(size,doinit)
endif
else
//sz i i+1 i+2
//[ ][ ][ ][ ]
set
i=cs_array1[0]+2
set
cs_array1[0]=i+rsize-1
endif
//It used to store size in the index equal to the array's id
// but that required the get/set functions to increment 1 in every index
// calculation. Instead, making size the previous index to the array works
if
(i<=8191)
then
set
cs_array1[i-1]=size
elseif
(i<=16382)
then
set
cs_array2[i-8192]=size
else
call
StoreInteger
(cs_cache,
I2S
(-i),
"size"
,size)
endif
if
(
not
doinit)
then
return
i
endif
// 3
//[i][i+1][i+2]
set
size=i+size-1
if
(size>=16382)
then
set
size=16381
endif
loop
exitwhen
(size<i)
or
(size<8191)
set
cs_array2[size-8191]=0
set
size=size-1
endloop
loop
exitwhen
(size<i)
set
cs_array1[size]=0
set
size=size-1
endloop
//call DisplayTextToPlayer(GetLocalPlayer(),0,0,I2S(i))
return
i
endfunction
//===============================================================================================================
// Remember to destroy arrays when you no longer need them, else new arrays will get slower after a bunch of
// arrays are active
//
function
DestroyArray
takes
integer
id
returns
nothing
local
integer
L
local
integer
loc
// local string k=I2S(-id)
local
integer
lstpace
if
(id<=8191)
then
set
L=cs_array1[cs_array1[id-1]]
elseif
(id<=16382)
then
set
L=cs_array1[cs_array2[id-8191]]
else
set
L=cs_array1[
GetStoredInteger
(cs_cache,
I2S
(-id),
"size"
)]
//No way you are gonna call DestroyArray without calling
//NewArray first, so we can use the gamecache variable directly instead
endif
set
lstpace=id+L-1
call
FlushStoredMission
(cs_cache,
I2S
(-id))
if
(lstpace>16382)
then
if
(lstpace==cs_array1[0])
then
//We just destroyed the array that happens to be at the end of the heap.
//Just get it back
set
cs_array1[0]=id-2
set
cs_array1[146]=1
else
//Add to the last
set
loc=cs_freeindexes[L+4096]
if
(loc==0)
then
set
loc=NewPair(id,0)
set
cs_freeindexes[L]=loc
set
cs_freeindexes[L+4096]=loc
else
set
cs_freeindexes[L+4096]= NewPair(id,0)
//we could just use: call SetPairY(loc, cs_freeindexes[L+4096] ) //but that's slower
if
(loc>=8189)
then
call
StoreInteger
(cs_cache,
"pairy"
,
I2S
(loc), cs_freeindexes[L+4096] )
else
set
cs_pairy[loc]=cs_freeindexes[L+4096]
endif
endif
endif
elseif
(lstpace==cs_array1[0])
then
//We just destroyed the array that happens to be at the end of the heap.
//Just get it back
set
cs_array1[0]=id-2
set
cs_array1[146]=1
else
set
loc=cs_freeindexes[L]
set
cs_freeindexes[L]=NewPair(id,loc)
if
(loc==0)
then
set
cs_freeindexes[L+4096]=cs_freeindexes[L]
endif
endif
endfunction
//================================================================================================================
// Int Set/Get array usage prototypes.
//
// These are the actual functions, the rest are just the result of copy paste, if these functions are updated
// the other ones should be updated as well (They are just return bugged variations)
//
function
SetArrayInt
takes
integer
id,
integer
index,
integer
val
returns
nothing
set
index=id+index
if
(index<8191)
then
set
cs_array1[index]=val
elseif
(index<16382)
then
set
cs_array2[index-8191]=val
else
call
StoreInteger
(cs_cache,
I2S
(-id),
I2S
(index),val)
endif
endfunction
function
GetArrayInt
takes
integer
id,
integer
index
returns
integer
set
index=id+index
if
(index<8191)
then
return
cs_array1[index]
elseif
(index<16382)
then
return
cs_array2[index-8191]
endif
return
GetStoredInteger
(cs_cache,
I2S
(-id),
I2S
(index))
endfunction
//================================================================================================================
// String Set/Get array
//
// Due String related return bug issues, these are forced to use gamecache
//
function
SetArrayString
takes
integer
id,
integer
index,
string
val
returns
nothing
call
StoreString
(cs_cache,
I2S
(-id),
I2S
(index),val)
endfunction
function
GetArrayString
takes
integer
id,
integer
index
returns
string
return
GetStoredString
(cs_cache,
I2S
(-id),
I2S
(index))
endfunction
//(Boolean is not needed)
//==========================================================================================================================
// Returns the size of an array (the specified by player one, not the actual size of it) should be useful.
//
function
GetArraySize
takes
integer
id
returns
integer
if
(id<=8191)
then
return
cs_array1[id-1]
elseif
(id<=16382)
then
return
cs_array2[id-8192]
endif
return
GetStoredInteger
(cs_cache,
I2S
(-id),
"size"
)
endfunction
//===========================================================================================================================
// Returns an array that is an exact copy of the given array
//
function
CloneArray
takes
integer
id
returns
integer
local
integer
sz
local
integer
i
local
integer
sz2
local
integer
x
local
integer
y
if
(id<=8191)
then
set
sz=cs_array1[id-1]
elseif
(id<=16382)
then
set
sz=cs_array2[id-8192]
else
set
sz=
GetStoredInteger
(cs_cache,
I2S
(-id),
"size"
)
//No way you are gonna call DestroyArray without calling
//NewArray first, so we can use the gamecache variable directly instead
endif
set
i=NewArray(sz,
false
)
set
sz2=i+sz-1
set
sz=id+sz-1
set
x=i
set
y=id
loop
exitwhen
((y>sz)
or
(y>=8191)
or
(x>=8191))
set
cs_array1[x]=cs_array1[y]
set
y=y+1
set
x=x+1
endloop
loop
exitwhen
((y>sz)
or
(y>=8191)
or
(x>=16382))
set
cs_array2[x-8191]=cs_array1[y]
set
y=y+1
set
x=x+1
endloop
loop
exitwhen
((y>sz)
or
(y>=8191))
call
StoreInteger
(cs_cache,
I2S
(-i),
I2S
(x-i),cs_array1[y])
set
x=y+1
set
y=y+1
endloop
//...
loop
exitwhen
((y>sz)
or
(y>=16382)
or
(x>=8191))
set
cs_array1[x]=cs_array2[y-8191]
set
y=y+1
set
x=x+1
endloop
loop
exitwhen
((y>sz)
or
(y>=16382)
or
(x>=16382))
set
cs_array2[x-8191]=cs_array2[y-8191]
set
y=y+1
set
x=x+1
endloop
loop
exitwhen
((y>sz)
or
(y>=16382))
call
StoreInteger
(cs_cache,
I2S
(-i),
I2S
(x-i),cs_array2[y-8191])
set
y=y+1
set
x=x+1
endloop
//...
loop
exitwhen
((y>sz)
or
(x>=8191))
set
cs_array1[x]=
GetStoredInteger
(cs_cache,
I2S
(-id),
I2S
(y-id))
set
y=y+1
set
x=x+1
endloop
loop
exitwhen
((y>sz)
or
(x>=16382))
set
cs_array2[x-8191]=
GetStoredInteger
(cs_cache,
I2S
(-id),
I2S
(y-id))
set
y=y+1
set
x=x+1
endloop
loop
exitwhen
(y>sz)
call
StoreInteger
(cs_cache,
I2S
(-i),
I2S
(x-i),
GetStoredInteger
(cs_cache,
I2S
(-id),
I2S
(y-id)))
set
y=y+1
set
x=x+1
endloop
return
i
endfunction
//==================================================================================================
// Attachable vars : Attacheable variables are what most other people call Handle Variables, they
// allow to relate data with any handle, using a label, and its value, the stuff auto flushes if
// the value is 0, false, "", or null .
//
// Differences between Attacheable variables and "Local Handle Variables" :
// - The names of the functions
// - The name of the function group does not cause confusion, it is difficult to say:
// "you should set local handle variables to null at the end of a function" since
// it sounds as if you were talking about the "Local Handle Variables"
// - And can work together with Tables.
//
// Gamecache stuff are NOT Case Sensitive, don't ever use "" for label (Crashes game!)
//
//
// Although locations and dynamic arrays are faster than gamecache, gamecache still keeps the flexibility
// Best thing to do in my opinion is to combine these options. By combining you can acquire gamecache
// flexibility and arrays/locs speed to solve a problem
//
//============================================================================================================
// For integers
//
function
AttachInt
takes
handle
h,
string
label,
integer
x
returns
nothing
if
x==0
then
call
FlushStoredInteger
(cs_cache,
I2S
(
GetHandleId
(h)),label)
else
call
StoreInteger
(cs_cache,
I2S
(
GetHandleId
(h)),label,x)
endif
endfunction
function
GetAttachedInt
takes
handle
h,
string
label
returns
integer
return
GetStoredInteger
(cs_cache,
I2S
(
GetHandleId
(h)), label)
endfunction
//=============================================================================================================
function
AttachReal
takes
handle
h,
string
label,
real
x
returns
nothing
if
x==0
then
call
FlushStoredReal
(cs_cache,
I2S
(
GetHandleId
(h)),label)
else
call
StoreReal
(cs_cache,
I2S
(
GetHandleId
(h)),label,x)
endif
endfunction
function
GetAttachedReal
takes
handle
h,
string
label
returns
real
return
GetStoredReal
(cs_cache,
I2S
(
GetHandleId
(h)),label)
endfunction
//=============================================================================================================
function
AttachBoolean
takes
handle
h,
string
label,
boolean
x
returns
nothing
if
not
x
then
call
FlushStoredBoolean
(cs_cache,
I2S
(
GetHandleId
(h)),label)
else
call
StoreBoolean
(cs_cache,
I2S
(
GetHandleId
(h)),label,x)
endif
endfunction
function
GetAttachedBoolean
takes
handle
h,
string
label
returns
boolean
return
GetStoredBoolean
(cs_cache,
I2S
(
GetHandleId
(h)),label)
endfunction
//=============================================================================================================
function
AttachString
takes
handle
h,
string
label,
string
x
returns
nothing
if
((x==
""
)
or
(x==
null
))
then
call
FlushStoredString
(cs_cache,
I2S
(
GetHandleId
(h)),label)
else
call
StoreString
(cs_cache,
I2S
(
GetHandleId
(h)),label,x)
endif
endfunction
function
GetAttachedString
takes
handle
h,
string
label
returns
string
return
GetStoredString
(cs_cache,
I2S
(
GetHandleId
(h)),label)
endfunction
//============================================================================================================
function
CleanAttachedVars
takes
handle
h
returns
nothing
call
FlushStoredMission
(cs_cache,
I2S
(
GetHandleId
(h)))
endfunction
//============================================================================================================
// Left for compat
function
CleanAttachedVars_NoSets
takes
handle
h
returns
nothing
call
FlushStoredMission
(cs_cache,
I2S
(
GetHandleId
(h)))
endfunction
//=============================================================================================
// Tables
//
// Tables are lame, the real name would be hash tables, they are just abbreviated usage
// of gamecache natives with the addition that you can also Copy the values of a table to
// another one, but don't expect it to be automatic, it must use a FieldData object to know
// which fields and of wich types to copy, Copying a table to another, with a lot of Fields,
// should surelly be lag friendly.
//
// The other thing about tables is that I can say that the Attached variables of a handle work
// inside a table and GetAttachmentTable which is just return bug and I2S , works to allow you
// to manipulate a handle's attached variables through a table.
//
// NewTable and DestroyTable were created to allow to create tables in the fly, but you can
// simply use strings for tables, but place the table names should be between "("")" for example
// "(mytable)" to avoid conflicts with other caster system stuff.
//
function
NewTableIndex
takes
nothing
returns
integer
local
integer
loc=cs_freeindexes[0]
local
integer
i
if
(loc!=0)
then
set
i=GetPairX(loc)
set
cs_freeindexes[0]=GetPairY(loc)
call
DestroyPair(loc)
return
i
endif
set
i=cs_array1[147]+1
set
cs_array1[147]=i
return
i
endfunction
function
NewTable
takes
nothing
returns
string
local
integer
loc=cs_freeindexes[0]
local
integer
i
if
(loc!=0)
then
set
i=GetPairX(loc)
set
cs_freeindexes[0]=GetPairY(loc)
call
DestroyPair(loc)
return
I2S
(i)
endif
set
i=cs_array1[147]+1
set
cs_array1[147]=i
return
I2S
(i)
endfunction
function
GetAttachmentTable
takes
handle
h
returns
string
return
I2S
(
GetHandleId
(h))
endfunction
//============================================================================================================
function
DestroyTable
takes
string
table
returns
nothing
local
integer
i=
S2I
(table)
local
integer
n
call
FlushStoredMission
(cs_cache,table)
if
((i>100)
and
(i<1000000))
then
//All right, more than 1000000 tables is just wrong.
if
(i==cs_array1[147])
then
set
cs_array1[147]=cs_array1[147]-1
else
set
cs_freeindexes[0]= NewPair(i,cs_freeindexes[0])
endif
endif
endfunction
//============================================================================================================
function
ClearTable
takes
string
table
returns
nothing
call
FlushStoredMission
(cs_cache,table)
endfunction
//============================================================================================================
function
SetTableInt
takes
string
table,
string
field,
integer
val
returns
nothing
if
(val==0)
then
call
FlushStoredInteger
(cs_cache,table,field)
else
call
StoreInteger
(cs_cache,table,field,val)
endif
endfunction
function
GetTableInt
takes
string
table,
string
field
returns
integer
return
GetStoredInteger
(cs_cache,table,field)
endfunction
//============================================================================================================
function
SetTableReal
takes
string
table,
string
field,
real
val
returns
nothing
if
(val==0)
then
call
FlushStoredReal
(cs_cache,table,field)
else
call
StoreReal
(cs_cache,table,field,val)
endif
endfunction
function
GetTableReal
takes
string
table,
string
field
returns
real
return
GetStoredReal
(cs_cache,table,field)
endfunction
//============================================================================================================
function
SetTableBoolean
takes
string
table,
string
field,
boolean
val
returns
nothing
if
(
not
(val))
then
call
FlushStoredBoolean
(cs_cache,table,field)
else
call
StoreBoolean
(cs_cache,table,field,val)
endif
endfunction
function
GetTableBoolean
takes
string
table,
string
field
returns
boolean
return
GetStoredBoolean
(cs_cache,table,field)
endfunction
//============================================================================================================
function
SetTableString
takes
string
table,
string
field,
string
val
returns
nothing
if
(val==
""
)
or
(val==
null
)
then
call
FlushStoredString
(cs_cache,table,field)
else
call
StoreString
(cs_cache,table,field,val)
endif
endfunction
function
GetTableString
takes
string
table,
string
field
returns
string
return
GetStoredString
(cs_cache,table,field)
endfunction
//============================================================================================================
// Returns true if the fiel contains a value different from 0, false, null, or "" (depending on the type)
// it is worthless to use this with boolean, since it would be the same as reading the boolean value
//
function
HaveSetField
takes
string
table,
string
field,
integer
fieldType
returns
boolean
if
(fieldType ==
bj_GAMECACHE_BOOLEAN
)
then
return
HaveStoredBoolean
(cs_cache,table,field)
elseif
(fieldType ==
bj_GAMECACHE_INTEGER
)
then
return
HaveStoredInteger
(cs_cache,table,field)
elseif
(fieldType ==
bj_GAMECACHE_REAL
)
then
return
HaveStoredReal
(cs_cache,table,field)
elseif
(fieldType ==
bj_GAMECACHE_STRING
)
then
return
HaveStoredString
(cs_cache,table,field)
endif
return
false
endfunction
//============================================================================================================
// Allows to copy a table to another one, but it needs a FieldData object to know which fields of which type
// it is supposed to copy.
//
function
CopyTable
takes
integer
FieldData,
string
sourceTable,
string
destTable
returns
nothing
local
integer
i=1
local
string
k=
I2S
(FieldData)
local
string
k2
local
string
k3
local
integer
n=
GetStoredInteger
(cs_cache,k,
"N"
)
local
integer
t
loop
exitwhen
(i>n)
set
k2=
I2S
(i)
set
t=
GetStoredInteger
(cs_cache,k,k2)
set
k3=
GetStoredString
(cs_cache,k,k2)
if
(t==
bj_GAMECACHE_BOOLEAN
)
then
if
(
HaveStoredBoolean
(cs_cache,sourceTable,k3))
then
call
StoreBoolean
(cs_cache,destTable,k3,
GetStoredBoolean
(cs_cache,sourceTable,k3))
else
call
FlushStoredBoolean
(cs_cache,destTable,k3)
endif
elseif
(t==
bj_GAMECACHE_INTEGER
)
then
if
(
HaveStoredInteger
(cs_cache,sourceTable,k3))
then
call
StoreInteger
(cs_cache,destTable,k3,
GetStoredInteger
(cs_cache,sourceTable,k3))
else
call
FlushStoredInteger
(cs_cache,destTable,k3)
endif
elseif
(t==
bj_GAMECACHE_REAL
)
then
if
(
HaveStoredReal
(cs_cache,sourceTable,k3))
then
call
StoreReal
(cs_cache,destTable,k3,
GetStoredReal
(cs_cache,sourceTable,k3))
else
call
FlushStoredReal
(cs_cache,destTable,k3)
endif
elseif
(t==
bj_GAMECACHE_STRING
)
then
if
(
HaveStoredString
(cs_cache,sourceTable,k3))
then
call
StoreString
(cs_cache,destTable,k3,
GetStoredString
(cs_cache,sourceTable,k3))
else
call
FlushStoredString
(cs_cache,destTable,k3)
endif
endif
set
i=i+1
endloop
endfunction
//=============================================================================================
// FieldData inherits from Table, was just designed to be used by CopyTable.
//
function
FieldData_Create
takes
nothing
returns
integer
return
NewTableIndex()
endfunction
//============================================================================================================
// valueType uses the same integer variables from blizzard.j :
// bj_GAMECACHE_BOOLEAN, bj_GAMECACHE_INTEGER, bj_GAMECACHE_REAL and bj_GAMECACHE_STRING
//
function
FieldData_AddField
takes
integer
fielddata,
string
field,
integer
valueType
returns
nothing
local
string
k=
I2S
(fielddata)
local
integer
n=
GetStoredInteger
(cs_cache,k,
"N"
)+1
local
string
k2=
I2S
(n)
call
StoreString
(cs_cache,k,k2,field)
call
StoreInteger
(cs_cache,k,k2,valueType)
call
StoreInteger
(cs_cache,k,
"N"
,n)
endfunction
//=============================================================================================
// Destroys Field Data
function
FieldData_Destroy
takes
integer
fielddata
returns
nothing
call
DestroyTable(
I2S
(fielddata))
endfunction
//=============================================================================================
// Pools
//
// A better name for pools would be sets, but by the time I made them I couldn't think of that
// name, besides the word set is already a JASS syntax word so it would have been problematic.
//
// Another naming failure is that values of a pool are called "items" but that conflicts with
// the word item that points to wc3 items, Pools can only store integer values, but if you want
// you can go and use the return bug on them.
//
function
CreatePool
takes
nothing
returns
integer
local
integer
i=NewArray(34,
false
)
call
SetArrayInt(i,0,0)
return
i
endfunction
function
ClearPool
takes
integer
poolid
returns
nothing
call
SetArrayInt(poolid,0,0)
//[0:integer:n]
call
FlushStoredMission
(cs_cache,
I2S
(-poolid))
endfunction
function
DestroyPool
takes
integer
poolid
returns
nothing
call
DestroyArray(poolid)
endfunction
function
PoolAddItem
takes
integer
poolid,
integer
value
returns
nothing
local
integer
n
local
string
k=
I2S
(-poolid)
local
string
vk=
"#"
+
I2S
(value)
if
not
HaveStoredInteger
(cs_cache,k,vk)
then
set
n=GetArrayInt(poolid,0)+1
//[0:integer:N]
call
StoreInteger
(cs_cache,k,vk,n)
if
(n>33)
then
call
StoreInteger
(cs_cache,k,
I2S
(n),value)
else
call
SetArrayInt(poolid,n,value)
endif
call
SetArrayInt(poolid,0,n)
//[0:integer:N]
endif
endfunction
function
PoolRemoveItem
takes
integer
poolid,
integer
value
returns
nothing
local
string
k=
I2S
(-poolid)
local
string
vk=
"#"
+
I2S
(value)
local
integer
p=
GetStoredInteger
(cs_cache,k,vk)
local
integer
n
if
(p!=0)
then
set
n=GetArrayInt(poolid,0)
//[0:integer:N]
call
FlushStoredInteger
( cs_cache, k, vk)
if
(n>p)
then
if
(n>33)
then
set
vk=
I2S
(n)
set
value=
GetStoredInteger
(cs_cache,k,vk)
call
FlushStoredInteger
(cs_cache,k,vk)
else
set
value=GetArrayInt(poolid,n)
endif
call
StoreInteger
(cs_cache,k,
"#"
+
I2S
(value),p)
if
(p>33)
then
call
StoreInteger
(cs_cache,k,
I2S
(p),value)
else
call
SetArrayInt(poolid,p,value)
endif
elseif
(p>33)
then
call
FlushStoredInteger
(cs_cache,k,
I2S
(p))
endif
call
SetArrayInt( poolid,0,n - 1)
//[0:integer:N]
endif
endfunction
//===================================================================================
function
PoolGetItem
takes
integer
poolid,
integer
itemn
returns
integer
if
(itemn>33)
then
return
GetStoredInteger
( cs_cache,
I2S
(-poolid),
I2S
(itemn))
endif
return
GetArrayInt(poolid,itemn)
endfunction
//===================================================================================
function
CountItemsInPool
takes
integer
poolid
returns
integer
return
GetArrayInt(poolid,0)
//[0:integer:N]
endfunction
//===================================================================================
// Removed : GetEnumPoolItem , ForPool and ForPool2 they are much worse than just
// using CountItemsInPool and PoolGetItem to iterate the pool
//
//===================================================================================
function
GetFirstOfPool
takes
integer
poolid
returns
integer
return
GetArrayInt(poolid,1)
//[1 is just the first of the pool]
endfunction
//===================================================================================
function
PoolPickRandomItem
takes
integer
poolid
returns
integer
local
integer
p=
GetRandomInt
( 1, GetArrayInt(poolid,0) )
if
(p>33)
then
return
GetStoredInteger
( cs_cache,
I2S
(-poolid),
I2S
(p))
endif
return
GetArrayInt(poolid,p)
endfunction
//===================================================================================
function
GetItemPositionInPool
takes
integer
poolid,
integer
it
returns
integer
return
GetStoredInteger
( cs_cache,
I2S
(-poolid),
"#"
+
I2S
(it))
endfunction
//===================================================================================
function
IsItemInPool
takes
integer
poolid,
integer
it
returns
boolean
return
(
HaveStoredInteger
( cs_cache,
I2S
(-poolid),
"#"
+
I2S
(it)) )
endfunction
//===================================================================================
// This had to be optimized for speed, if it was just a loop using the above functions
// that would have been too slow to be worth keeping. That's a bad thing about JASS
// it is such an slow language that code reusability always has the cost of speed
//
function
PoolAddPool
takes
integer
sourcepoolid,
integer
destpoolid
returns
nothing
local
integer
a=1
local
integer
n=GetArrayInt( sourcepoolid,0)
//[0:integer:N]
local
integer
dn=GetArrayInt( destpoolid,0)
//[0:integer:N]
local
string
sk=
I2S
(-sourcepoolid)
local
string
k=
I2S
(-destpoolid)
local
integer
v
local
string
vk
loop
exitwhen
(a>n)
if
(a>33)
then
set
v=
GetStoredInteger
(cs_cache,sk,
I2S
(a))
else
set
v=GetArrayInt(sourcepoolid,a)
endif
set
vk=
"#"
+
I2S
(v)
if
not
HaveStoredInteger
(cs_cache,k,vk)
then
set
dn=dn+1
call
StoreInteger
(cs_cache,k,vk,dn)
if
(dn>33)
then
call
StoreInteger
(cs_cache,k,
I2S
(dn),v)
else
call
SetArrayInt(destpoolid,dn,v)
endif
endif
set
a=a+1
endloop
call
SetArrayInt(destpoolid,0,dn)
//[0:integer:N]
endfunction
//=============================================================================================
// Oh darn, After making PoolAddPool I don't feel like writting this one
// All right I am at least make the get code
//
function
PoolRemovePool
takes
integer
sourcepoolid,
integer
destpoolid
returns
nothing
local
integer
a=1
local
integer
n=GetArrayInt( sourcepoolid,0)
//[0:integer:N]
local
integer
v
local
string
sk=
I2S
(-sourcepoolid)
loop
exitwhen
a>n
if
(a>33)
then
set
v=
GetStoredInteger
(cs_cache,sk,
I2S
(a) )
else
set
v=GetArrayInt(sourcepoolid,a)
endif
call
PoolRemoveItem( destpoolid, v)
set
a=a+1
endloop
endfunction
//===================================================================================
// Adds a tokenized string to a pool,
// Example: PoolAddS(udg_p, "1;2;3;4") will add to the udg_p pool : 1,2,3 and 4
//
function
PoolAddS
takes
integer
poolid,
string
s
returns
nothing
local
integer
i=0
local
integer
st
local
string
c
set
s=s+
";"
set
st=0
loop
set
c=
SubString
(s, i, i+1)
exitwhen
(c ==
""
)
or
(c ==
null
)
if
(c ==
";"
)
then
call
PoolAddItem( poolid,
S2I
(
SubString
(s, st, i)) )
set
st=i+1
endif
set
i=i+1
endloop
endfunction
//===================================================================================
// Converts a tokenized string into a pool,
// Example: S2Pool( "1;2;3;4") will return a pool that has 1,2,3 and 4 inside
//
function
S2Pool
takes
string
s
returns
integer
local
integer
spool= CreatePool()
call
PoolAddS(spool,s)
return
spool
endfunction
//===================================================================================
// Does the opposite of S2Pool, debugging is a good use for this function.
//
function
Pool2S
takes
integer
P
returns
string
local
integer
N=CountItemsInPool(P)
local
integer
i
local
string
s
if
(N>=1)
then
set
s=
I2S
(PoolGetItem(P,1) )
set
i=2
else
return
""
endif
loop
exitwhen
(i>N)
set
s=s+
";"
+
I2S
(PoolGetItem(P,i))
set
i=i+1
endloop
return
s
endfunction
//=============================================================================================================
// Fixes a lame bug by blizzard related to the custom script section (The condition of the if statement might
// actually be true.
//
function
Pool_Percent
takes
nothing
returns
string
if
(
"%"
==
""
)
then
return
"%%"
endif
return
"%"
endfunction
function
Pool_SetupCharMap
takes
nothing
returns
nothing
local
string
cm=
".................................!.#$"
+Pool_Percent()+
"&'()*+,-./0123456789:;<=>.@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~..."
local
integer
i=0
local
string
c
if
HaveStoredInteger
(cs_cache,
"charmap_upper"
,
"A"
)
then
return
endif
loop
set
c=
SubString
(cm,i,i+1)
exitwhen
(c==
null
)
or
(c==
""
)
if
(c!=
"."
)
then
if
c==
StringCase
(c,
true
)
then
call
StoreInteger
(cs_cache,
"charmap_upper"
,c,i)
else
call
StoreInteger
(cs_cache,
"charmap_lower"
,c,i)
endif
endif
set
i=i+1
endloop
endfunction
function
Pool_Rawcode2Int
takes
string
s
returns
integer
local
string
c
local
integer
i=0
local
integer
r=0
loop
exitwhen
i>3
set
c=
SubString
(s,i,i+1)
set
r=r*256
if
c==
StringCase
(c,
true
)
then
set
r=r+
GetStoredInteger
(cs_cache,
"charmap_upper"
,c)
else
set
r=r+
GetStoredInteger
(cs_cache,
"charmap_lower"
,c)
endif
set
i=i+1
endloop
return
r
endfunction
function
PoolAddRawcodes_thread
takes
nothing
returns
nothing
//Threaded because I don't want it to halt execution for no reason
//
local
string
s=
bj_lastPlayedMusic
local
integer
poolid=
bj_groupEnumTypeId
local
string
c
local
integer
i=0
local
integer
st=0
set
s=s+
";"
loop
set
c=
SubString
(s, i, i+1)
exitwhen
(c ==
""
)
or
(c ==
null
)
if
c ==
";"
then
call
PoolAddItem(poolid, Pool_Rawcode2Int(
SubString
(s,st,i) ))
set
st=i+1
endif
set
i=i+1
endloop
endfunction
//=====================================================================================================================
// Adds a string of tokenized rawcodes to a pool
// Example: PoolAddRawcodes(udg_p,"A000;A001") will add 'A000' and 'A001' to the pool
//
// (Saves some lines, but is not as good efficiency wise)
//
function
PoolAddRawcodes
takes
integer
poolid,
string
s
returns
nothing
local
string
b=
bj_lastPlayedMusic
set
bj_groupEnumTypeId
=poolid
set
bj_lastPlayedMusic
=s
call
ExecuteFunc
(
"PoolAddRawcodes_thread"
)
set
bj_lastPlayedMusic
=b
endfunction
//===================================================================================================================
// Converts a tokenized string of rawcodes into a pool,
// Example: Rawcodes2Pool( "A000;A001;AHbz;S000") will return a pool that has 'A000,'A001','AHbx' and 'S000' inside
//
// (Saves some lines, but is not as good efficiency wise)
//
function
Rawcodes2Pool
takes
string
s
returns
integer
local
integer
spool= CreatePool()
call
PoolAddRawcodes(spool,s)
return
spool
endfunction
//===================================================================================================================
// A subproduct of the Pool's Rawcode support is that we can easily have this function so I am including it even if
// it has nothing to do with data storage.
//
// takes "Aloc" and converts it into 'Aloc'
// it is different to the Pool_Rawcode2Int function in that it is safe to use it when it is the first CSCache
// function ever used. But it is a little slower (wc3mapoptimizer should make it as fast though)
//
function
CS_Rawcode2Int
takes
string
s
returns
integer
local
string
c
local
integer
i=0
local
integer
r=0
loop
exitwhen
i>3
set
c=
SubString
(s,i,i+1)
set
r=r*256
if
c==
StringCase
(c,
true
)
then
set
r=r+
GetStoredInteger
(cs_cache,
"charmap_upper"
,c)
else
set
r=r+
GetStoredInteger
(cs_cache,
"charmap_lower"
,c)
endif
set
i=i+1
endloop
return
r
endfunction
endlibrary
«
Last Edit: December 23, 2017, 07:23:36 PM by moyack
»
Print
Pages:
1
Go Up
« previous
next »
WC3 Modding Information Center
Forum
Warcraft (WC3) Modding
Warcraft III Resources
Warcraft III Spells and Systems
Codes & Snippets
Faux HandleVars & CSCache
Suggested Topics
How to make a Campaign AI
Started by
moyack
Replies: 1
Views: 28749
Jass Tutorials
[System] Unit Recycler & Simple Damage Detection System
Started by
moyack
Replies: 6
Views: 18995
Codes & Snippets
Bugs, features & Reports about this site network.
Started by
moyack
Replies: 1
Views: 8999
Site Discussion
Vampire's Realm
Started by
sonofjay
Replies: 5
Views: 11864
Warcraft III Projects
PortaMx-SEF 1.54
|
PortaMx © 2008-2015
,
PortaMx corp.
Search
Username
Password
Always stay logged in
Forgot your password?