Chaos_Knight
New Member
- Reaction score
- 39
When i save my map, it says Library Redeclared: PUI.
Here is the code.
And yes, when i save it, i check the lines above, ifits any unended librarys.
//Chaos_Knight
Here is the code.
And yes, when i save it, i check the lines above, ifits any unended librarys.
JASS:
//==============================================================================
// PUI -- Perfect Unit Indexing by Cohadar -- v4.2
//==============================================================================
//
// PURPOUSE:
// * Extending UnitUserData()
// * This is basically perfect hashing algorithm for units
//
// HOW TO USE:
// * You have only one function at your disposal GetUnitIndex(unit)
// It will return a unique index for each unit in range 1..4095
//
// * What you will do with that index is all up to you
// Of course using global arrays is the most obvious choice
// Advanced jassers will think of a couple of more clever ones ofc.
//
// PROS:
// * You can use any number of systems that previously could not work together
// because they all required exclusive access of UnitUserData()
//
// * You can also use this to attach spell data structs to casters
//
// * There are no SetUnitIndex() or ClearUnitIndex() function here
// Each unit gets assigned one index that cannot be changed
// That index will be automatically recycled when unit is removed from the game.
//
// CONS:
// * This system uses UnitUserData() itself
// That means that if you have this sys you must recode
// any other system that uses UnitUserData() to use this sys instead
//
// * If you use UnitIndex for arrays of non-native types (timers, effects and similar)
// you must check if timer on that index already exists before you create a new one.
// This can happen if GetUnitIndex() assigns a recycled index (index of some dead and removed unit)
// to the newly created unit for witch you intended to use timer for
//
// * All in all this is not a sys for newbies, it gives great power,
// but it requires knowledge and carefull handling
//
// * You cannot have more than 4095 units on your map with pui assigned index
// (at the same time)
//
// DETAILS:
// * System is using unit array to keep track of all units with an index.
// Array is periodically checked for removed units,
// when removed unit is found, index is recycled.
// Indexes have "decay time" of 3 (three) sec to prevent bugs
// caused by attaching to "Can't Raise, Does not decay" type units,
// or by using RemoveUnit() function
//
// SYSTEM COMMANDS: (debug mode only, red player only)
//
// * type -index to display indexes of currently selected units
//
// * type -topindex to display total number of assigned unit indexes
//
// HOW TO IMPORT:
// * Just create a trigger named PUI
// * convert it to text and replace the whole trigger text with this one
//
//==============================================================================
library PUI initializer Init
globals
//==============================================================================
// INDEX_DECAY_TIME = INDEX_DECAY_TICKS * SEGMENT_CHECK_PERIOD
// For current constants 12*0.25 = 3 seconds
//
// Every 512 units on map will add 1 more second to index decay time.
// So if you have 1024 units, index decay time will be 3 + 2 = 5 sec
//
// Index decay time starts AFTER unit is decayed/removed from game.
//==============================================================================
//-----------------------------------------------
private constant integer INDEX_DECAY_TICKS = 12
//-----------------------------------------------
private constant integer INDEX_LIMIT = 4096
private constant integer INDEX_SEGMENT_SIZE = 128
private constant real SEGMENT_CHECK_PERIOD = 0.25
//-----------------------------------------------
private integer TopIndex = 0
private integer array IndexArray
private integer array IndexDecayTick
private unit array UnitArray
private integer RecycleSegment = 0
endglobals
//==============================================================================
private function RecycleIndex takes nothing returns boolean
local integer i
local integer op_limiter
local integer temp
set i = RecycleSegment * INDEX_SEGMENT_SIZE + 1
if i > TopIndex then
set RecycleSegment = 0
set i = 1 // zero index is not used
endif
set op_limiter = i + INDEX_SEGMENT_SIZE - 1
loop
exitwhen i > TopIndex
exitwhen i > op_limiter
if IndexDecayTick<i> == 0 then
if (GetUnitUserData(UnitArray<i>)==0) then
set IndexDecayTick<i> = 1
endif
else
set IndexDecayTick<i> = IndexDecayTick<i> + 1
if IndexDecayTick<i> >= INDEX_DECAY_TICKS then
set UnitArray<i> = UnitArray[TopIndex]
set UnitArray[TopIndex] = null
set IndexDecayTick<i> = IndexDecayTick[TopIndex]
set IndexDecayTick[TopIndex] = 0
set temp = IndexArray<i>
set IndexArray<i> = IndexArray[TopIndex]
set IndexArray[TopIndex] = temp
//debug call BJDebugMsg("|c0000FF00PUI: Index recycled #" + I2S(IndexArray[TopIndex]))
set TopIndex = TopIndex - 1
endif
endif
set i = i + 1
endloop
set RecycleSegment = RecycleSegment + 1
return false
endfunction
//==============================================================================
private function DisplayTopIndex takes nothing returns nothing
call BJDebugMsg("TopIndex = " + I2S(TopIndex))
endfunction
//===========================================================================
private function DisplaySelectedEnum takes nothing returns nothing
call BJDebugMsg( "PUI: index for unit {" + ( GetUnitName(GetEnumUnit()) + ( "} = " + I2S(GetUnitUserData(GetEnumUnit())) ) ) )
endfunction
//===========================================================================
private function DisplaySelected takes nothing returns nothing
local group g = CreateGroup()
call SyncSelections()
call GroupEnumUnitsSelected(g, Player(0), null)
call ForGroup(g, function DisplaySelectedEnum)
call DestroyGroup(g)
set g = null
endfunction
//==============================================================================
// Main and only function exported by this library
// WARNING: this function can return zero, you should always check that.
//==============================================================================
function GetUnitIndex takes unit whichUnit returns integer
local integer index
if whichUnit == null then
call BJDebugMsg("|c00FF0000ERROR: PUI - Index requested for null unit")
return 0
endif
set index = GetUnitUserData(whichUnit)
if index == 0 then
set TopIndex = TopIndex + 1
set index = IndexArray[TopIndex]
set UnitArray[TopIndex] = whichUnit
call SetUnitUserData(whichUnit, index)
set index = GetUnitUserData(whichUnit)
// this happens when requesting unit index for removed unit
if index == 0 then
call BJDebugMsg("|c00FFCC00WARNING: PUI - Bad unit handle")
endif
//debug call BJDebugMsg("|c00FFCC00PUI: Index assigned #" + I2S(index))
endif
return index
endfunction
//==============================================================================
private function Init takes nothing returns nothing
local integer i
local trigger trig
set i = 1
loop
exitwhen i >= INDEX_LIMIT
set IndexArray<i> = i
set i = i + 1
endloop
set trig = CreateTrigger()
call TriggerRegisterTimerEventPeriodic( trig, SEGMENT_CHECK_PERIOD )
call TriggerAddCondition( trig, Condition(function RecycleIndex) )
debug set trig = CreateTrigger()
debug call TriggerRegisterPlayerChatEvent( trig, Player(0), "-index", true )
debug call TriggerAddAction( trig, function DisplaySelected )
debug set trig = CreateTrigger()
debug call TriggerRegisterPlayerChatEvent( trig, Player(0), "-topindex", true )
debug call TriggerAddAction( trig, function DisplayTopIndex )
endfunction
endlibrary
</i></i></i></i></i></i></i></i></i></i></i>
//Chaos_Knight