Jeck - Card ID collisions, cache fixes, cache deleted pooling.

* mtgid now defaults to 0.
 * TextScroller will not update when empty.
 * Cache now moves WCachedResources we're finished with to a garbage pool for later use (to reduce memory fragmentation). 
 * Demo still crashes... but I'm thinking that has to do with fragmentation, not a leak?
This commit is contained in:
wagic.jeck
2009-09-19 01:48:42 +00:00
parent 5d57693d31
commit 4b8d344bcd
11 changed files with 893 additions and 738 deletions

View File

@@ -1,276 +1,278 @@
[card] [card]
text=When Ambassador Oak comes enters the battlefield, put a 1/1 green Elf Warrior creature token onto the battlefield. text=When Ambassador Oak comes enters the battlefield, put a 1/1 green Elf Warrior creature token onto the battlefield.
id=152998 id=152998
name=Ambassador Oak name=Ambassador Oak
auto=token(Elf Warrior,creature elf,1/1,green) auto=token(Elf Warrior,creature elf,1/1,green)
rarity=C rarity=C
mana={3}{G} mana={3}{G}
type=Creature type=Creature
subtype=Treefolk Warrior subtype=Treefolk Warrior
power=3 power=3
toughness=3 toughness=3
[/card] [/card]
[card] [card]
text=At the beginning of your upkeep, you lose 1 life and put a 1/1 black Faerie Rogue creature token with flying into play. text=At the beginning of your upkeep, you lose 1 life and put a 1/1 black Faerie Rogue creature token with flying into play.
auto=@each my upkeep:life-1 controller auto=@each my upkeep:life-1 controller
auto=@each my upkeep:token(Faerie,creature faerie,1/1,flying black) auto=@each my upkeep:token(Faerie,creature faerie,1/1,flying black)
id=152648 id=152648
name=Bitterblossom name=Bitterblossom
rarity=R rarity=R
mana={1}{B} mana={1}{B}
type=Enchantment type=Enchantment
subtype=Faerie subtype=Faerie
[/card] [/card]
[card] [card]
text={T}, Pay 1 life: Add {G} to your mana pool. text={T}, Pay 1 life: Add {G} to your mana pool.
id=152705 id=152705
auto={T}:Add {G} && life:-1 controller auto={T}:Add {G} && life:-1 controller
name=Blightsoil Druid name=Blightsoil Druid
rarity=C rarity=C
mana={1}{B} mana={1}{B}
type=Creature type=Creature
subtype=Elf Druid subtype=Elf Druid
power=1 power=1
toughness=2 toughness=2
[/card] [/card]
[card] [card]
text=Trample Borderland Behemoth gets +4/+4 for each other Giant you control. text=Trample Borderland Behemoth gets +4/+4 for each other Giant you control.
id=153102 id=153102
name=Borderland Behemoth name=Borderland Behemoth
auto=foreach(giant|myBattlefield):4/4 other auto=foreach(giant|myBattlefield):4/4 other
rarity=R rarity=R
mana={5}{R}{R} mana={5}{R}{R}
type=Creature type=Creature
subtype=Giant Warrior subtype=Giant Warrior
power=4 power=4
toughness=4 toughness=4
abilities=trample abilities=trample
[/card] [/card]
[card] [card]
text=Enchant creature {1}{W}: Put a +1/+1 counter on enchanted creature. text=Enchant creature {1}{W}: Put a +1/+1 counter on enchanted creature.
id=152838 id=152838
name=Daily Regimen name=Daily Regimen
target=creature target=creature
auto={1}{W}:counter(1/1) auto={1}{W}:counter(1/1)
rarity=U rarity=U
mana={W} mana={W}
type=Enchantment type=Enchantment
subtype=Aura subtype=Aura
[/card] [/card]
[card] [card]
text=Return target nonland permanent to its owner's hand. text=Return target nonland permanent to its owner's hand.
id=152727 id=152727
name=Disperse name=Disperse
target=creature,artifact,enchantment target=creature,artifact,enchantment
auto=moveTo(ownerHand) auto=moveTo(ownerHand)
rarity=C rarity=C
mana={1}{U} mana={1}{U}
type=Instant type=Instant
[/card] [/card]
[card] [card]
text= text=
id=153003 id=153003
name=Elvish Warrior name=Elvish Warrior
rarity=C rarity=C
mana={G}{G} mana={G}{G}
type=Creature type=Creature
subtype=Elf Warrior subtype=Elf Warrior
power=2 power=2
toughness=3 toughness=3
[/card] [/card]
[card] [card]
text=Flying {U}: Put Fencer Clique on top of its owner's library. text=Flying {U}: Put Fencer Clique on top of its owner's library.
id=157424 id=157424
name=Fencer Clique name=Fencer Clique
rarity=C rarity=C
mana={2}{U}{U} mana={2}{U}{U}
auto={U}:moveTo(ownerlibrary) auto={U}:moveTo(ownerlibrary)
type=Creature type=Creature
subtype=Faerie Soldier subtype=Faerie Soldier
power=3 power=3
toughness=2 toughness=2
abilities=flying abilities=flying
[/card] [/card]
[card] [card]
text=Festercreep comes into play with a +1/+1 counter on it. {1}{B}, Remove a +1/+1 counter from Festercreep: All other creatures get -1/-1 until end of turn. text=Festercreep comes into play with a +1/+1 counter on it. {1}{B}, Remove a +1/+1 counter from Festercreep: All other creatures get -1/-1 until end of turn.
id=152944 id=152944
name=Festercreep name=Festercreep
rarity=C rarity=C
mana={1}{B} mana={1}{B}
auto=counter(1/1) auto=counter(1/1)
auto={1}{B}:counter(1/1,-1) && lord(creature) -1/-1 auto={1}{B}:counter(1/1,-1) && lord(creature) -1/-1
type=Creature type=Creature
subtype=Elemental subtype=Elemental
power=0 power=0
toughness=0 toughness=0
[/card] [/card]
[card] [card]
text=Search your library for an enchantment card, reveal it, and put it into your hand. Then shuffle your library. text=Search your library for an enchantment card, reveal it, and put it into your hand. Then shuffle your library.
id=152938 id=152938
name=Idyllic Tutor name=Idyllic Tutor
rarity=R rarity=R
mana={2}{W} mana={2}{W}
auto=moveTo(myhand) target(enchantment|myLibrary) auto=moveTo(myhand) target(enchantment|myLibrary)
type=Sorcery type=Sorcery
[/card] [/card]
[card] [card]
text= text=
id=152967 id=152967
name=Indomitable Ancients name=Indomitable Ancients
rarity=R rarity=R
mana={2}{W}{W} mana={2}{W}{W}
type=Creature type=Creature
subtype=Treefolk Warrior subtype=Treefolk Warrior
power=2 power=2
toughness=10 toughness=10
[/card] [/card]
[card] [card]
text=Target creature gets +1/+0 and gains first strike until end of turn. text=Target creature gets +1/+0 and gains first strike until end of turn.
id=152563 id=152563
name=Kindled Fury name=Kindled Fury
target=creature target=creature
auto=1/0 auto=1/0
auto=first strike auto=first strike
rarity=C rarity=C
mana={R} mana={R}
type=Instant type=Instant
[/card] [/card]
[card] [card]
name=Inspired Sprite name=Inspired Sprite
mana={U}{3} mana={U}{3}
type=Creature type=Creature
subtype=Faerie Wizard subtype=Faerie Wizard
text=Flash. Flying. Whenever you cast a Wizard spell, you may untap Inspired Sprite. {T}: Draw a card, then discard a card. text=Flash. Flying. Whenever you cast a Wizard spell, you may untap Inspired Sprite. {T}: Draw a card, then discard a card.
abilities=flash,flying abilities=flash,flying
auto=@movedTo(wizard|mystack):may untap auto=@movedTo(wizard|mystack):may untap
auto={T}:draw:1 && moveto(graveyard) target(*|myhand) auto={T}:draw:1 && moveto(graveyard) target(*|myhand)
power=2 power=2
toughness=2 toughness=2
rarity=U rarity=U
[/card] [/card]
[card] [card]
text=Knight creatures you control have double strike. text=Knight creatures you control have double strike.
id=153279 id=153279
auto=lord(creature|mybattlefield) double strike auto=lord(creature|mybattlefield) double strike
name=Kinsbaile Cavalier name=Kinsbaile Cavalier
rarity=R rarity=R
mana={3}{W} mana={3}{W}
type=Creature type=Creature
subtype=Kithkin Knight subtype=Kithkin Knight
power=2 power=2
toughness=2 toughness=2
[/card] [/card]
[card] [card]
text=Target player discards X cards at random. text=Target player discards X cards at random.
id=157422 id=157422
name=Mind Shatter name=Mind Shatter
alias=1167 alias=1167
rarity=R rarity=R
mana={X}{B}{B} mana={X}{B}{B}
type=Sorcery type=Sorcery
[/card] [/card]
[card] [card]
text=Draw X cards. text=Draw X cards.
id=152628 id=152628
name=Mind Spring name=Mind Spring
alias=1192 alias=1192
rarity=R rarity=R
mana={X}{U}{U} mana={X}{U}{U}
type=Sorcery type=Sorcery
[/card] [/card]
[card] [card]
text=Counter target noncreature spell. text=Counter target noncreature spell.
id=152570 id=152570
target=*(-creature)|stack target=*(-creature)|stack
auto=fizzle auto=fizzle
name=Negate name=Negate
rarity=C rarity=C
mana={1}{U} mana={1}{U}
type=Instant type=Instant
[/card] [/card]
[card] [card]
text=Fear text=Fear
id=152718 id=152718
name=Prickly Boggart name=Prickly Boggart
rarity=C rarity=C
mana={B} mana={B}
type=Creature type=Creature
subtype=Goblin Rogue subtype=Goblin Rogue
power=1 power=1
toughness=1 toughness=1
abilities=fear abilities=fear
[/card] [/card]
[card] [card]
text=Sacrifice an Elemental: Seething Pathblazer gets +2/+0 and gains first strike until end of turn. text=Sacrifice an Elemental: Seething Pathblazer gets +2/+0 and gains first strike until end of turn.
id=153101 id=153101
name=Seething Pathblazer name=Seething Pathblazer
auto={S(elemental|myBattlefield)}:2/0 && first strike auto={S(elemental|myBattlefield)}:2/0 && first strike
rarity=C rarity=C
mana={2}{R} mana={2}{R}
type=Creature type=Creature
subtype=Elemental Warrior subtype=Elemental Warrior
power=2 power=2
toughness=2 toughness=2
[/card] [/card]
[card] [card]
Name=Shinewend id=152659
Mana={1}{W} Name=Shinewend
Type=Creature Mana={1}{W}
subtype=Elemental Type=Creature
Text=Flying. Shinewend enters the battlefield with a +1/+1 counter on it. {1}{W}, Remove a +1/+1 counter from Shinewend: Destroy target enchantment. subtype=Elemental
auto=counter(1/1,1) Text=Flying. Shinewend enters the battlefield with a +1/+1 counter on it. {1}{W}, Remove a +1/+1 counter from Shinewend: Destroy target enchantment.
auto={1}{W}:counter(1/1,-1) && destroy target(enchantment) auto=counter(1/1,1)
abilities=flying auto={1}{W}:counter(1/1,-1) && destroy target(enchantment)
Power=0 abilities=flying
toughness=0 Power=0
Rarity=C toughness=0
[/card] Rarity=C
[card] [/card]
Name=Stingmoggie [card]
Mana={3}{R} id=152704
Type=Creature Name=Stingmoggie
subtype=Elemental Mana={3}{R}
Text=Stingmoggie enters the battlefield with two +1/+1 counters on it. {3}{R}, Remove a +1/+1 counter from Stingmoggie: Destroy target artifact or land. Type=Creature
auto=counter(1/1,2) subtype=Elemental
auto={1}{W}:counter(1/1,-1) && destroy target(artifact,land) Text=Stingmoggie enters the battlefield with two +1/+1 counters on it. {3}{R}, Remove a +1/+1 counter from Stingmoggie: Destroy target artifact or land.
Power=0 auto=counter(1/1,2)
toughness=0 auto={1}{W}:counter(1/1,-1) && destroy target(artifact,land)
Rarity=C Power=0
[/card] toughness=0
[card] Rarity=C
text=Vengeful Firebrand has haste as long as a Warrior card is in your graveyard. R: Vengeful Firebrand gets +1/+0 until end of turn. [/card]
id=153153 [card]
name=Vengeful Firebrand text=Vengeful Firebrand has haste as long as a Warrior card is in your graveyard. R: Vengeful Firebrand gets +1/+0 until end of turn.
auto=aslongas(warrior|mygraveyard) haste id=153153
auto={R}:1/0 name=Vengeful Firebrand
rarity=R auto=aslongas(warrior|mygraveyard) haste
mana={3}{R} auto={R}:1/0
type=Creature rarity=R
subtype=Elemental Warrior mana={3}{R}
power=5 type=Creature
toughness=2 subtype=Elemental Warrior
[/card] power=5
[card] toughness=2
text=Destroy target nonblack creature. Put a 1/1 black Faerie Rogue creature token with flying into play. [/card]
id=157426 [card]
target=creature[-black] text=Destroy target nonblack creature. Put a 1/1 black Faerie Rogue creature token with flying into play.
auto=destroy id=157426
auto=token(Faerie Rogue,Creature Faerie,1/1,flying black) target=creature[-black]
name=Violet Pall auto=destroy
rarity=C auto=token(Faerie Rogue,Creature Faerie,1/1,flying black)
mana={4}{B} name=Violet Pall
type=Tribal Instant rarity=C
subtype=Faerie mana={4}{B}
[/card] type=Tribal Instant
[card] subtype=Faerie
text={3}{B}, Sacrifice a Goblin: Put two 1/1 black Goblin Rogue creature tokens onto the battlefield. [/card]
id=153011 [card]
auto={3}{B}{S(goblin|myBattlefield)}:token(Goblin Rogue,Creature Goblin,1/1,black) && token(Goblin Rogue,Creature Goblin,1/1,black) text={3}{B}, Sacrifice a Goblin: Put two 1/1 black Goblin Rogue creature tokens onto the battlefield.
name=Weirding Shaman id=153011
rarity=R auto={3}{B}{S(goblin|myBattlefield)}:token(Goblin Rogue,Creature Goblin,1/1,black) && token(Goblin Rogue,Creature Goblin,1/1,black)
mana={1}{B} name=Weirding Shaman
type=Creature rarity=R
subtype=Goblin Shaman mana={1}{B}
power=2 type=Creature
toughness=1 subtype=Goblin Shaman
power=2
toughness=1
[/card] [/card]

View File

@@ -1,342 +1,342 @@
[card] [card]
text=First strike, protection from white text=First strike, protection from white
id=130715 id=130715
name=Blood Knight name=Blood Knight
rarity=U rarity=U
type=Creature type=Creature
subtype=human knight subtype=human knight
mana={R}{R} mana={R}{R}
power=2 power=2
toughness=2 toughness=2
abilities=first strike,protection from white abilities=first strike,protection from white
color=Red color=Red
[/card] [/card]
[card] [card]
text=Target creature gets +3/+3 until end of turn. text=Target creature gets +3/+3 until end of turn.
target=creature target=creature
auto=3/3 auto=3/3
id=122373 id=122373
name=Brute Force name=Brute Force
rarity=C rarity=C
color=Red color=Red
type=Instant type=Instant
mana={R} mana={R}
[/card] [/card]
[card] [card]
text=Other white creatures get +1/+1. Nonwhite creatures get -1/-1. Pay 2 life: Return Crovax, Ascendant Hero to its owner's hand. text=Other white creatures get +1/+1. Nonwhite creatures get -1/-1. Pay 2 life: Return Crovax, Ascendant Hero to its owner's hand.
abilities=legendary abilities=legendary
auto=lord(creature[white]) 1/1 auto=lord(creature[white]) 1/1
auto=loard(creature[-white] -1/-1 auto=loard(creature[-white] -1/-1
auto={0}life:-2:moveTo(ownerhand) auto={0}life:-2:moveTo(ownerhand)
id=122487 id=122487
name=Crovax, Ascendant Hero name=Crovax, Ascendant Hero
rarity=R rarity=R
color=White color=White
type=Creature type=Creature
mana={4}{W}{W} mana={4}{W}{W}
power=4 power=4
subtype=Human Lord subtype=Human Lord
toughness=4 toughness=4
[/card] [/card]
[card] [card]
text=Destroy all creatures. They can't be regenerated. text=Destroy all creatures. They can't be regenerated.
auto=bury all(creature) auto=bury all(creature)
id=122423 id=122423
name=Damnation name=Damnation
rarity=R rarity=R
type=Sorcery type=Sorcery
mana={2}{B}{B} mana={2}{B}{B}
color=Black color=Black
[/card] [/card]
[card] [card]
text=Creatures you control get +1/+1. text=Creatures you control get +1/+1.
auto=lord(creature|myinplay) 1/1 auto=lord(creature|myinplay) 1/1
id=122367 id=122367
name=Gaea's Anthem name=Gaea's Anthem
rarity=R rarity=R
type=Enchantment type=Enchantment
mana={1}{G}{G} mana={1}{G}{G}
color=Green color=Green
[/card] [/card]
[card] [card]
text=Trample, haste At end of turn, sacrifice Groundbreaker. text=Trample, haste At end of turn, sacrifice Groundbreaker.
abilities=trample,haste abilities=trample,haste
auto=@next endofturn:bury auto=@next endofturn:bury
id=122429 id=122429
name=Groundbreaker name=Groundbreaker
rarity=R rarity=R
color=Green color=Green
type=Creature type=Creature
mana={G}{G}{G} mana={G}{G}{G}
power=6 power=6
subtype=Elemental subtype=Elemental
toughness=1 toughness=1
[/card] [/card]
[card] [card]
text=Draw three cards. text=Draw three cards.
auto=draw:3 auto=draw:3
id=122362 id=122362
name=Harmonize name=Harmonize
rarity=U rarity=U
color=Green color=Green
type=Sorcery type=Sorcery
mana={2}{G}{G} mana={2}{G}{G}
[/card] [/card]
[card] [card]
text=Hedge Troll gets +1/+1 as long as you control a Plains. {W}: Regenerate Hedge Troll. text=Hedge Troll gets +1/+1 as long as you control a Plains. {W}: Regenerate Hedge Troll.
auto=aslongas(plains|myinplay) 1/1 auto=aslongas(plains|myinplay) 1/1
auto={W}:regenerate auto={W}:regenerate
id=122405 id=122405
name=Hedge Troll name=Hedge Troll
rarity=U rarity=U
color=Green color=Green
type=Creature type=Creature
mana={2}{G} mana={2}{G}
power=2 power=2
subtype=Troll Cleric subtype=Troll Cleric
toughness=2 toughness=2
[/card] [/card]
[card] [card]
text=Flying {W}{W}{W}: Regenerate Malach of the Dawn. text=Flying {W}{W}{W}: Regenerate Malach of the Dawn.
abilities=flying abilities=flying
auto={W}{W}{W}:regenerate auto={W}{W}{W}:regenerate
id=122481 id=122481
name=Malach of the Dawn name=Malach of the Dawn
rarity=U rarity=U
color=White color=White
type=Creature type=Creature
mana={2}{W}{W} mana={2}{W}{W}
power=2 power=2
subtype=Angel subtype=Angel
toughness=4 toughness=4
[/card] [/card]
[card] [card]
text=Sunlance deals 3 damage to target nonwhite creature. text=Sunlance deals 3 damage to target nonwhite creature.
target=creature[-white] target=creature[-white]
auto=Damage:3 auto=Damage:3
id=122355 id=122355
name=Sunlance name=Sunlance
rarity=C rarity=C
color=White color=White
type=Sorcery type=Sorcery
mana={w} mana={w}
[/card] [/card]
[card] [card]
text=Flying, Vigilance text=Flying, Vigilance
id=125873 id=125873
name=Serra Sphinx name=Serra Sphinx
rarity=R rarity=R
type=Creature type=Creature
subtype=Sphinx subtype=Sphinx
mana={3}{U}{U} mana={3}{U}{U}
power=4 power=4
toughness=4 toughness=4
abilities=vigilance,flying abilities=vigilance,flying
color=Blue color=Blue
[/card] [/card]
[card] [card]
text=Swampwalk {G}: Regenerate Mire Boa. text=Swampwalk {G}: Regenerate Mire Boa.
id=122420 id=122420
name=Mire Boa name=Mire Boa
rarity=C rarity=C
type=Creature type=Creature
subtype=Snake subtype=Snake
mana={1}{G} mana={1}{G}
power=2 power=2
toughness=1 toughness=1
auto={G}:regenerate auto={G}:regenerate
abilities=swampwalk abilities=swampwalk
color=Green color=Green
[/card] [/card]
[card] [card]
text=Reach text=Reach
id=122268 id=122268
name=Needlepeak Spider name=Needlepeak Spider
rarity=C rarity=C
type=Creature type=Creature
subtype=Spider subtype=Spider
mana={3}{R} mana={3}{R}
power=4 power=4
toughness=2 toughness=2
abilities=reach abilities=reach
color=Red color=Red
[/card] [/card]
[card] [card]
text={T}:Prodigal Pyromancer deals 1 damage to target creature or player. text={T}:Prodigal Pyromancer deals 1 damage to target creature or player.
id=134752 id=122338
name=Prodigal Pyromancer name=Prodigal Pyromancer
rarity=C rarity=C
type=Creature type=Creature
subtype=Human Wizard subtype=Human Wizard
mana={2}{R} mana={2}{R}
power=1 power=1
toughness=1 toughness=1
auto={T}:damage:1 target(creature,player) auto={T}:damage:1 target(creature,player)
color=Red color=Red
[/card] [/card]
#[card] #[card]
#text=At end of turn, if no creatures are in play, sacrifice Pyrohemia. {R}: Pyrohemia #deals 1 damage to each creature and each player. #text=At end of turn, if no creatures are in play, sacrifice Pyrohemia. {R}: Pyrohemia #deals 1 damage to each creature and each player.
#alias=1172 #alias=1172
#id=122436 #id=122436
#name=Pyrohemia #name=Pyrohemia
#rarity=U #rarity=U
#type=Enchantment #type=Enchantment
#mana={2}{R}{R} #mana={2}{R}{R}
#color=Red #color=Red
#[/card] #[/card]
[card] [card]
text={B}, {T}:Tap target creature. text={B}, {T}:Tap target creature.
id=130718 id=130718
name=Rathi Trapper name=Rathi Trapper
rarity=C rarity=C
type=Creature type=Creature
subtype=Human Rebel Rogue subtype=Human Rebel Rogue
mana={1}{B} mana={1}{B}
power=1 power=1
toughness=2 toughness=2
auto={B}{T}:tap target(creature) auto={B}{T}:tap target(creature)
color=Black color=Black
[/card] [/card]
[card] [card]
text={W}:Regenerate Revered Dead. text={W}:Regenerate Revered Dead.
id=122282 id=122282
name=Revered Dead name=Revered Dead
rarity=C rarity=C
type=Creature type=Creature
subtype=Spirit Soldier subtype=Spirit Soldier
mana={1}{W} mana={1}{W}
power=1 power=1
toughness=1 toughness=1
auto={W}:regenerate auto={W}:regenerate
color=White color=White
[/card] [/card]
[card] [card]
text=Destroy target nonwhite permanent. text=Destroy target nonwhite permanent.
target=*[-white] target=*[-white]
auto=destroy auto=destroy
id=122435 id=122435
name=Saltblast name=Saltblast
rarity=U rarity=U
color=White color=White
type=Sorcery type=Sorcery
mana={3}{W}{W} mana={3}{W}{W}
[/card] [/card]
[card] [card]
text={T}:Target creature gets -2/-0 until end of turn. text={T}:Target creature gets -2/-0 until end of turn.
id=124037 id=124037
name=Saltfield Recluse name=Saltfield Recluse
rarity=C rarity=C
type=Creature type=Creature
subtype=Human Rebel Cleric subtype=Human Rebel Cleric
mana={2}{W} mana={2}{W}
power=1 power=1
toughness=2 toughness=2
auto={T}:-2/-0 target(creature) auto={T}:-2/-0 target(creature)
color=White color=White
[/card] [/card]
[card] [card]
text=Sacrifice Seal of Primordium: Destroy target artifact or enchantment. text=Sacrifice Seal of Primordium: Destroy target artifact or enchantment.
auto={S}:destroy target(artifact,enchantment) auto={S}:destroy target(artifact,enchantment)
id=130816 id=130816
name=Seal of Primordium name=Seal of Primordium
rarity=C rarity=C
type=Enchantment type=Enchantment
mana={1}{G} mana={1}{G}
color=Green color=Green
[/card] [/card]
[card] [card]
text=Enchant creature Enchanted creature can't attack or block. Enchanted creature has "{T}:Add one mana of any color to your mana pool." text=Enchant creature Enchanted creature can't attack or block. Enchanted creature has "{T}:Add one mana of any color to your mana pool."
auto=cantattack,cantblock auto=cantattack,cantblock
auto={T}:add:{W} auto={T}:add:{W}
auto={T}:add:{U} auto={T}:add:{U}
auto={T}:add:{B} auto={T}:add:{B}
auto={T}:add:{R} auto={T}:add:{R}
auto={T}:add:{G} auto={T}:add:{G}
id=131004 id=131004
name=Utopia Vow name=Utopia Vow
rarity=C rarity=C
type=Enchantment type=Enchantment
mana={1}{G} mana={1}{G}
color=Green color=Green
subtype=Aura subtype=Aura
[/card] [/card]
[card] [card]
text=Enchant creature Enchanted creature has lifelink. text=Enchant creature Enchanted creature has lifelink.
auto=lifelink auto=lifelink
id=122366 id=122366
name=Vampiric link name=Vampiric link
rarity=U rarity=U
type=Enchantment type=Enchantment
mana={B} mana={B}
color=Black color=Black
subtype=Aura subtype=Aura
[/card] [/card]
[card] [card]
text=All Sliver creatures have trample. text=All Sliver creatures have trample.
id=126015 id=126015
name=Battering Sliver name=Battering Sliver
rarity=C rarity=C
type=Creature type=Creature
subtype=Sliver subtype=Sliver
mana={5}{R} mana={5}{R}
power=4 power=4
toughness=4 toughness=4
auto=lord(Sliver) trample auto=lord(Sliver) trample
abilities=trample abilities=trample
color=Red color=Red
[/card] [/card]
[card] [card]
text=All Sliver creatures have haste. text=All Sliver creatures have haste.
id=126018 id=126018
name=Reflex Sliver name=Reflex Sliver
rarity=C rarity=C
type=Creature type=Creature
subtype=Sliver subtype=Sliver
mana={3}{G} mana={3}{G}
power=2 power=2
toughness=2 toughness=2
auto=lord(Sliver) haste auto=lord(Sliver) haste
abilities=haste abilities=haste
color=Green color=Green
[/card] [/card]
[card] [card]
text=All Sliver creatures get +1/+1. text=All Sliver creatures get +1/+1.
id=125879 id=125879
name=Sinew Sliver name=Sinew Sliver
rarity=C rarity=C
type=Creature type=Creature
subtype=Sliver subtype=Sliver
mana={1}{W} mana={1}{W}
power=2 power=2
toughness=2 toughness=2
auto=lord(Sliver) 1/1 auto=lord(Sliver) 1/1
color=White color=White
[/card] [/card]
[card] [card]
text=All Sliver creatures have first strike. text=All Sliver creatures have first strike.
id=126022 id=126022
name=Spitting Sliver name=Spitting Sliver
rarity=C rarity=C
type=Creature type=Creature
subtype=Sliver subtype=Sliver
mana={4}{B} mana={4}{B}
power=3 power=3
toughness=3 toughness=3
auto=lord(Sliver) first strike auto=lord(Sliver) first strike
abilities=first strike abilities=first strike
color=Black color=Black
[/card] [/card]
[card] [card]
text=All Sliver creatures have vigilance. text=All Sliver creatures have vigilance.
id=124044 id=124044
name=Synchronous Sliver name=Synchronous Sliver
rarity=C rarity=C
type=Creature type=Creature
subtype=Sliver subtype=Sliver
mana={4}{U} mana={4}{U}
power=3 power=3
toughness=3 toughness=3
auto=lord(Sliver) vigilance auto=lord(Sliver) vigilance
abilities=vigilance abilities=vigilance
color=Blue color=Blue
[/card] [/card]

View File

@@ -20,6 +20,7 @@ class GameStateMenu: public GameState, public JGuiListener
JTexture * bgTexture; JTexture * bgTexture;
JTexture * movingWTexture; JTexture * movingWTexture;
JQuad * mBg; JQuad * mBg;
JQuad * mSplash;
JQuad * mMovingW; JQuad * mMovingW;
float mCreditsYPos; float mCreditsYPos;
int currentState; int currentState;

View File

@@ -15,7 +15,8 @@ public:
WResource(); WResource();
virtual ~WResource(); virtual ~WResource();
virtual void Trash()=0; //Delete the cacheActual.
virtual void Nullify()=0; //For when our size is 0, so we don't free anything by mistake. virtual void Nullify()=0; //For when our size is 0, so we don't free anything by mistake.
virtual unsigned long size()=0; //Size of cached item in bytes. virtual unsigned long size()=0; //Size of cached item in bytes.
virtual bool isGood()=0; //Return true if this has data. virtual bool isGood()=0; //Return true if this has data.
@@ -38,6 +39,8 @@ public:
friend class WResourceManager; friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache; template<class cacheItem,class cacheActual> friend class WCache;
virtual ~WCachedResource() {};
virtual void Refresh(string filename)=0; //Basically calls Attempt(filename) and remaps in situ. virtual void Refresh(string filename)=0; //Basically calls Attempt(filename) and remaps in situ.
virtual bool Attempt(string filename, int submode, int & error)=0; //Returns true if we've loaded our data and isGood(). virtual bool Attempt(string filename, int submode, int & error)=0; //Returns true if we've loaded our data and isGood().
}; };
@@ -48,6 +51,7 @@ public:
WTrackedQuad(string _resname); WTrackedQuad(string _resname);
~WTrackedQuad(); ~WTrackedQuad();
void Nullify(); void Nullify();
void Trash();
unsigned long size(); unsigned long size();
bool isGood(); bool isGood();
@@ -73,6 +77,7 @@ public:
bool compare(JTexture * t) {return (t == texture);}; bool compare(JTexture * t) {return (t == texture);};
void Nullify(); void Nullify();
void Trash();
JTexture * Actual(); //Return this texture as is. Does not make a new one. JTexture * Actual(); //Return this texture as is. Does not make a new one.
JQuad * GetQuad(string resname); JQuad * GetQuad(string resname);
@@ -86,6 +91,7 @@ protected:
JTexture * texture; JTexture * texture;
bool bVRAM; bool bVRAM;
vector<WTrackedQuad*> trackedQuads; vector<WTrackedQuad*> trackedQuads;
static vector<WTrackedQuad*> garbageTQs;
}; };
class WCachedParticles: public WCachedResource{ class WCachedParticles: public WCachedResource{
@@ -96,6 +102,7 @@ public:
~WCachedParticles(); ~WCachedParticles();
void Nullify(); void Nullify();
void Trash();
void Refresh(string filename); void Refresh(string filename);
unsigned long size(); unsigned long size();
bool isGood(); bool isGood();
@@ -114,6 +121,7 @@ public:
WCachedSample(); WCachedSample();
~WCachedSample(); ~WCachedSample();
void Nullify(); void Nullify();
void Trash();
bool compare(JSample * s) {return (s == sample);}; bool compare(JSample * s) {return (s == sample);};
unsigned long size(); unsigned long size();
bool isGood(); bool isGood();

View File

@@ -19,10 +19,11 @@
//Hard Limits. //Hard Limits.
#define MAX_CACHE_OBJECTS 400 #define MAX_CACHE_OBJECTS HUGE_CACHE_ITEMS
#define MAX_CACHE_ATTEMPTS 10 #define MAX_CACHE_ATTEMPTS 10
#define MAX_CACHE_MISSES 200 #define MAX_CACHE_MISSES 200
#define MAX_CACHED_SAMPLES 0 #define MAX_CACHED_SAMPLES 0
#define MAX_CACHE_GARBAGE 10
enum ENUM_WRES_INFO{ enum ENUM_WRES_INFO{
WRES_UNLOCKED = 0, //Resource is unlocked. WRES_UNLOCKED = 0, //Resource is unlocked.
@@ -61,7 +62,8 @@ enum ENUM_CACHE_ERROR{
CACHE_ERROR_NONE = 0, CACHE_ERROR_NONE = 0,
CACHE_ERROR_NOT_CACHED = CACHE_ERROR_NONE, CACHE_ERROR_NOT_CACHED = CACHE_ERROR_NONE,
CACHE_ERROR_404, CACHE_ERROR_404,
CACHE_ERROR_BAD, CACHE_ERROR_BAD, //Something went wrong with item->attempt()
CACHE_ERROR_BAD_ALLOC, //Couldn't allocate item
CACHE_ERROR_LOST, CACHE_ERROR_LOST,
CACHE_ERROR_NOT_MANAGED, CACHE_ERROR_NOT_MANAGED,
}; };
@@ -89,15 +91,17 @@ public:
protected: protected:
bool RemoveItem(cacheItem * item, bool force = true); //Removes an item, deleting it. if(force), ignores locks / permanent bool RemoveItem(cacheItem * item, bool force = true); //Removes an item, deleting it. if(force), ignores locks / permanent
bool UnlinkCache(cacheItem * item); //Removes an item from our cache, does not delete it. Use with care. bool UnlinkCache(cacheItem * item); //Removes an item from our cache, does not delete it. Use with care.
bool Delete(cacheItem * item); //Call SAFE_DELETE on cacheItem. If maxCached == 0, nullify first. (This means you have to free that cacheActual later!) bool Delete(cacheItem * item); //SAFE_DELETE and garbage collect. If maxCached == 0, nullify first. (This means you have to free that cacheActual later!)
cacheItem* Get(string id, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL); //Subordinate to Retrieve. cacheItem* Get(string id, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL); //Subordinate to Retrieve.
cacheItem* AttemptNew(string filename, int submode); //Attempts a new cache item, progressively clearing cache if it fails. cacheItem* AttemptNew(string filename, int submode); //Attempts a new cache item, progressively clearing cache if it fails.
cacheItem* Recycle(); //Returns a cache item from the trash.
string makeID(string filename, int submode); //Makes an ID appropriate to the submode. string makeID(string filename, int submode); //Makes an ID appropriate to the submode.
string makeFilename(string id, int submode); //Makes a filename from an ID. string makeFilename(string id, int submode); //Makes a filename from an ID.
map<string,cacheItem*> cache; map<string,cacheItem*> cache;
map<string,cacheItem*> managed; //Cache can be arbitrarily large, so managed items are seperate. map<string,cacheItem*> managed; //Cache can be arbitrarily large, so managed items are seperate.
vector<cacheItem*> garbage; //Garbage collection.
unsigned long totalSize; unsigned long totalSize;
unsigned long cacheSize; unsigned long cacheSize;
@@ -138,6 +142,7 @@ public:
void Release(JQuad * quad); void Release(JQuad * quad);
void Release(JSample * sample); void Release(JSample * sample);
bool RemoveOldest();
bool Cleanup(); //Force a cleanup. Return false if nothing removed. bool Cleanup(); //Force a cleanup. Return false if nothing removed.
void ClearMisses(); //Remove all cache misses. void ClearMisses(); //Remove all cache misses.

View File

@@ -64,6 +64,9 @@ GameStateMenu::GameStateMenu(GameApp* parent): GameState(parent)
mGuiController = NULL; mGuiController = NULL;
subMenuController = NULL; subMenuController = NULL;
gameTypeMenu = NULL; gameTypeMenu = NULL;
mSplash = NULL;
mBg = NULL;
mMovingW = NULL;
//bgMusic = NULL; //bgMusic = NULL;
timeIndex = 0; timeIndex = 0;
angleMultiplier = MIN_ANGLE_MULTIPLIER; angleMultiplier = MIN_ANGLE_MULTIPLIER;
@@ -315,6 +318,7 @@ void GameStateMenu::Update(float dt)
std::ifstream file(options.profileFile(PLAYER_COLLECTION,"",false).c_str()); std::ifstream file(options.profileFile(PLAYER_COLLECTION,"",false).c_str());
if(file){ if(file){
file.close(); file.close();
resources.Release(mSplash);
currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_NONE; currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_NONE;
}else{ }else{
currentState = MENU_STATE_MAJOR_FIRST_TIME | MENU_STATE_MINOR_NONE; currentState = MENU_STATE_MAJOR_FIRST_TIME | MENU_STATE_MINOR_NONE;
@@ -414,9 +418,10 @@ void GameStateMenu::Render()
renderer->ClearScreen(ARGB(0,0,0,0)); renderer->ClearScreen(ARGB(0,0,0,0));
JLBFont * mFont = resources.GetJLBFont(Constants::MENU_FONT); JLBFont * mFont = resources.GetJLBFont(Constants::MENU_FONT);
if ((currentState & MENU_STATE_MAJOR) == MENU_STATE_MAJOR_LOADING_CARDS){ if ((currentState & MENU_STATE_MAJOR) == MENU_STATE_MAJOR_LOADING_CARDS){
JQuad* splashQuad = resources.RetrieveTempQuad("splash.jpg"); if(!mSplash)
if (splashQuad){ mSplash = resources.RetrieveQuad("splash.jpg");
renderer->RenderQuad(splashQuad,0,0); if (mSplash){
renderer->RenderQuad(mSplash,0,0);
}else{ }else{
char text[512]; char text[512];
sprintf(text, _("LOADING SET: %s").c_str(), mCurrentSetName); sprintf(text, _("LOADING SET: %s").c_str(), mCurrentSetName);

View File

@@ -69,6 +69,7 @@ int MTGCard::init(){
colors[i] = 0; colors[i] = 0;
} }
setId = 0; setId = 0;
mtgid = 0;
magicText = ""; magicText = "";
spellTargetType = ""; spellTargetType = "";
alias = 0; alias = 0;

View File

@@ -279,7 +279,7 @@ int MTGAllCards::readConfLine(std::ifstream &file, int set_id){
char outBuf[4096]; char outBuf[4096];
sprintf(outBuf,"warning, card id collision! : %i - %s\n", newId, tempCard->name.c_str()); sprintf(outBuf,"warning, card id collision! : %i - %s\n", newId, tempCard->name.c_str());
OutputDebugString (outBuf); OutputDebugString (outBuf);
delete tempCard; SAFE_DELETE(tempCard);
}else{ }else{
ids.push_back(newId); ids.push_back(newId);
collection[newId] = tempCard; collection[newId] = tempCard;

View File

@@ -1,66 +1,68 @@
#include "../include/TextScroller.h" #include "../include/TextScroller.h"
#include <JLBFont.h> #include <JLBFont.h>
TextScroller::TextScroller(JLBFont * font, float x, float y, float width, float speed):JGuiObject(0){ TextScroller::TextScroller(JLBFont * font, float x, float y, float width, float speed):JGuiObject(0){
mFont = font; mFont = font;
mWidth = width; mWidth = width;
mSpeed = speed; mSpeed = speed;
mX = x; mX = x;
mY = y; mY = y;
start = -width; start = -width;
timer = 0; timer = 0;
currentId = 0; currentId = 0;
mRandom = 0; mRandom = 0;
} }
void TextScroller::setRandom(int mode){ void TextScroller::setRandom(int mode){
mRandom = mode; mRandom = mode;
if (mRandom && strings.size()){ if (mRandom && strings.size()){
currentId = (rand() % strings.size()); currentId = (rand() % strings.size());
mText = strings[currentId]; mText = strings[currentId];
} }
} }
void TextScroller::Add(string text){ void TextScroller::Add(string text){
if (!strings.size()) mText = text; if (!strings.size()) mText = text;
strings.push_back(text); strings.push_back(text);
} }
void TextScroller::Reset(){ void TextScroller::Reset(){
strings.clear(); strings.clear();
} }
void TextScroller::Update(float dt){ void TextScroller::Update(float dt){
start+=mSpeed*dt; if(!strings.size())
if (start > mFont->GetStringWidth(mText.c_str())){ return;
start = -mWidth; start+=mSpeed*dt;
if (mRandom){ if (start > mFont->GetStringWidth(mText.c_str())){
currentId = (rand() % strings.size()); start = -mWidth;
}else{ if (mRandom){
currentId++; currentId = (rand() % strings.size());
if (currentId > strings.size()-1)currentId = 0; }else{
} currentId++;
mText = strings[currentId]; if (currentId > strings.size()-1)currentId = 0;
} }
mText = strings[currentId];
} }
void TextScroller::Render(){ }
mFont->DrawString(mText.c_str(),mX,mY,JGETEXT_LEFT,start,mWidth);
} void TextScroller::Render(){
mFont->DrawString(mText.c_str(),mX,mY,JGETEXT_LEFT,start,mWidth);
ostream& TextScroller::toString(ostream& out) const }
{
return out << "TextScroller ::: mText : " << mText ostream& TextScroller::toString(ostream& out) const
<< " ; tempText : " << tempText {
<< " ; mFont : " << mFont return out << "TextScroller ::: mText : " << mText
<< " ; mWidth : " << mWidth << " ; tempText : " << tempText
<< " ; mSpeed : " << mSpeed << " ; mFont : " << mFont
<< " ; mX,mY : " << mX << "," << mY << " ; mWidth : " << mWidth
<< " ; start : " << start << " ; mSpeed : " << mSpeed
<< " ; timer : " << timer << " ; mX,mY : " << mX << "," << mY
<< " ; strings : ?" // << strings << " ; start : " << start
<< " ; currentId : " << currentId << " ; timer : " << timer
<< " ; mRandom : " << mRandom; << " ; strings : ?" // << strings
} << " ; currentId : " << currentId
<< " ; mRandom : " << mRandom;
}

View File

@@ -59,6 +59,8 @@ void WResource::hit(){
lastTime = resources.nowTime(); lastTime = resources.nowTime();
} }
//WCachedTexture //WCachedTexture
vector<WTrackedQuad*> WCachedTexture::garbageTQs;
WCachedTexture::WCachedTexture(){ WCachedTexture::WCachedTexture(){
#ifdef DEBUG_CACHE #ifdef DEBUG_CACHE
OutputDebugString("Cached texture created.\n"); OutputDebugString("Cached texture created.\n");
@@ -122,7 +124,13 @@ bool WCachedTexture::ReleaseQuad(JQuad* quad){
tq->unlock(); tq->unlock();
if(!tq->isLocked()){ if(!tq->isLocked()){
SAFE_DELETE(tq); if(WCachedTexture::garbageTQs.size() < MAX_CACHE_GARBAGE){
tq->Trash();
garbageTQs.push_back(tq);
}
else
SAFE_DELETE(tq);
trackedQuads.erase(it); trackedQuads.erase(it);
} }
@@ -157,7 +165,14 @@ WTrackedQuad * WCachedTexture::GetTrackedQuad(float offX, float offY, float widt
if(tq == NULL){ if(tq == NULL){
allocated = true; allocated = true;
tq = NEW WTrackedQuad(resname); vector<WTrackedQuad*>::iterator gtq = WCachedTexture::garbageTQs.begin();
if(gtq != WCachedTexture::garbageTQs.end())
{
tq = *gtq;
garbageTQs.erase(gtq);
}
else
tq = NEW WTrackedQuad(resname);
} }
if(tq == NULL) if(tq == NULL)
@@ -314,6 +329,22 @@ void WCachedTexture::Nullify(){
if(texture) if(texture)
texture = NULL; texture = NULL;
} }
void WCachedTexture::Trash(){
SAFE_DELETE(texture);
vector<WTrackedQuad*>::iterator it;
WTrackedQuad * tq = NULL;
for(it=trackedQuads.begin();it!=trackedQuads.end();it++){
tq = (*it);
if(WCachedTexture::garbageTQs.size() > MAX_CACHE_GARBAGE)
SAFE_DELETE(tq);
else{
WCachedTexture::garbageTQs.push_back(tq);
}
}
trackedQuads.clear();
}
//WCachedSample //WCachedSample
void WCachedSample::Nullify(){ void WCachedSample::Nullify(){
@@ -322,6 +353,10 @@ void WCachedSample::Nullify(){
} }
} }
void WCachedSample::Trash(){
SAFE_DELETE(sample);
}
WCachedSample::WCachedSample(){ WCachedSample::WCachedSample(){
#ifdef DEBUG_CACHE #ifdef DEBUG_CACHE
OutputDebugString("Cached sample created.\n"); OutputDebugString("Cached sample created.\n");
@@ -452,11 +487,20 @@ void WCachedParticles::Nullify(){
particles = NULL; particles = NULL;
} }
void WCachedParticles::Trash(){
SAFE_DELETE(particles);
}
//WTrackedQuad //WTrackedQuad
void WTrackedQuad::Nullify() { void WTrackedQuad::Nullify() {
quad = NULL; quad = NULL;
} }
void WTrackedQuad::Trash(){
resname.clear();
SAFE_DELETE(quad);
}
#if defined DEBUG_CACHE #if defined DEBUG_CACHE
int WTrackedQuad::totalTracked = 0; int WTrackedQuad::totalTracked = 0;
#endif #endif

View File

@@ -10,9 +10,30 @@
#include "../include/WResourceManager.h" #include "../include/WResourceManager.h"
WResourceManager resources; WResourceManager resources;
unsigned int vTime = 0; unsigned int vTime = 0;
void handle_new_failure(){
OutputDebugString("NEW failed. Attempting to clear cache.");
#ifdef DEBUG_CACHE
resources.debugMessage = "Emergency cache cleanup!";
#endif
if(!resources.RemoveOldest()){
OutputDebugString("Nothing to clear from cache. Abort.");
abort();
}
}
bool WResourceManager::RemoveOldest(){
if(sampleWCache.RemoveOldest())
return true;
if(textureWCache.RemoveOldest())
return true;
if(psiWCache.RemoveOldest())
return true;
return false;
}
//WResourceManager //WResourceManager
void WResourceManager::DebugRender(){ void WResourceManager::DebugRender(){
JRenderer* renderer = JRenderer::GetInstance(); JRenderer* renderer = JRenderer::GetInstance();
@@ -168,18 +189,27 @@ WResourceManager::~WResourceManager(){
SAFE_DELETE(wm); SAFE_DELETE(wm);
} }
managedQuads.clear(); managedQuads.clear();
//Remove all our reserved WTrackedQuads from WCachedTexture
vector<WTrackedQuad*>::iterator g;
for(g=WCachedTexture::garbageTQs.begin();g!=WCachedTexture::garbageTQs.end();g++){
WTrackedQuad * tq = *g;
SAFE_DELETE(tq);
}
LOG("==Successfully Destroyed WResourceManager=="); LOG("==Successfully Destroyed WResourceManager==");
} }
JQuad * WResourceManager::RetrieveCard(MTGCard * card, int style, int submode){ JQuad * WResourceManager::RetrieveCard(MTGCard * card, int style, int submode){
//Cards are never, ever resource managed, so just check cache. //Cards are never, ever resource managed, so just check cache.
if(!card)
return NULL;
submode = submode | TEXTURE_SUB_CARD; submode = submode | TEXTURE_SUB_CARD;
string filename = card->getSetName(); string filename = card->getSetName();
filename += "/"; filename += "/";
filename += card->getImageName(); filename += card->getImageName();
JQuad * jq = RetrieveQuad(filename,0,0,0,0,filename,style,submode|TEXTURE_SUB_5551); JQuad * jq = RetrieveQuad(filename,0,0,0,0,"",style,submode|TEXTURE_SUB_5551);
if(jq){ if(jq){
jq->SetHotSpot(jq->mTex->mWidth / 2, jq->mTex->mHeight / 2); jq->SetHotSpot(jq->mTex->mWidth / 2, jq->mTex->mHeight / 2);
@@ -335,9 +365,8 @@ void WResourceManager::Release(JQuad * quad){
break; break;
} }
//Releasing a quad doesn't release the associated texture-- it might be needed later. if(it != textureWCache.cache.end() && it->second)
//if(it != textureWCache.cache.end() && it->second) textureWCache.RemoveItem(it->second,false); //won't remove locked.
// textureWCache.RemoveItem(it->second,false); //won't remove locked.
} }
void WResourceManager::ClearMisses(){ void WResourceManager::ClearMisses(){
@@ -400,6 +429,9 @@ JTexture * WResourceManager::RetrieveTexture(string filename, int style, int sub
case CACHE_ERROR_404: case CACHE_ERROR_404:
debugMessage = "File not found: "; debugMessage = "File not found: ";
break; break;
case CACHE_ERROR_BAD_ALLOC:
debugMessage = "Out of memory: ";
break;
case CACHE_ERROR_BAD: case CACHE_ERROR_BAD:
debugMessage = "Cache bad: "; debugMessage = "Cache bad: ";
break; break;
@@ -892,10 +924,6 @@ bool WCache<cacheItem, cacheActual>::RemoveOldest(){
} }
if(oldest != cache.end() && oldest->second && !oldest->second->isLocked()){ if(oldest != cache.end() && oldest->second && !oldest->second->isLocked()){
unsigned long isize = oldest->second->size();
cacheSize -= isize;
totalSize -= isize;
cacheItems--;
#if defined DEBUG_CACHE #if defined DEBUG_CACHE
lastExpired = oldest->first; lastExpired = oldest->first;
#endif #endif
@@ -915,13 +943,8 @@ void WCache<cacheItem, cacheActual>::Clear(){
next = it; next = it;
next++; next++;
if(it->second){ if(it->second)
unsigned long isize = it->second->size();
totalSize -= isize;
cacheSize -= isize;
Delete(it->second); Delete(it->second);
cacheItems--;
}
cache.erase(it); cache.erase(it);
} }
for(it = managed.begin(); it != managed.end();it=next){ for(it = managed.begin(); it != managed.end();it=next){
@@ -942,11 +965,7 @@ void WCache<cacheItem, cacheActual>::ClearUnlocked(){
next++; next++;
if(it->second && !it->second->isLocked()){ if(it->second && !it->second->isLocked()){
unsigned long isize = it->second->size();
totalSize -= isize;
cacheSize -= isize;
Delete(it->second); Delete(it->second);
cacheItems--;
cache.erase(it); cache.erase(it);
} }
else if(!it->second){ else if(!it->second){
@@ -983,6 +1002,19 @@ void WCache<cacheItem, cacheActual>::Resize(unsigned long size, int items){
else else
maxCached = items; maxCached = items;
} }
template <class cacheItem, class cacheActual>
cacheItem* WCache<cacheItem, cacheActual>::Recycle(){
typename vector<cacheItem*>::iterator it = garbage.begin();
if(it == garbage.end())
return NULL;
cacheItem * item = (*it);
garbage.erase(it);
return item;
}
template <class cacheItem, class cacheActual> template <class cacheItem, class cacheActual>
cacheItem* WCache<cacheItem, cacheActual>::AttemptNew(string filename, int submode){ cacheItem* WCache<cacheItem, cacheActual>::AttemptNew(string filename, int submode){
if(submode & CACHE_EXISTING){ //Should never get this far. if(submode & CACHE_EXISTING){ //Should never get this far.
@@ -990,24 +1022,46 @@ cacheItem* WCache<cacheItem, cacheActual>::AttemptNew(string filename, int submo
return NULL; return NULL;
} }
cacheItem* item = NEW cacheItem; cacheItem* item = NULL;
mError = CACHE_ERROR_NONE; item = Recycle();
if(item == NULL){
try{
item = NEW cacheItem;
mError = CACHE_ERROR_NONE;
}
catch(std::bad_alloc){
SAFE_DELETE(item);
}
}
if(item == NULL || !item->Attempt(filename,submode,mError)){ if(item == NULL || !item->Attempt(filename,submode,mError)){
//No such file. Fail. //No such file. Fail.
if(item && mError == CACHE_ERROR_404){ if(item && mError == CACHE_ERROR_404){
Delete(item); if(garbage.size() < MAX_CACHE_GARBAGE){
item->Trash();
garbage.push_back(item);
}
else
SAFE_DELETE(item);
return NULL; return NULL;
} }
for(int attempt=0;attempt<10;attempt++){ for(int attempt=0;attempt<10;attempt++){
if(!RemoveOldest()) if(!RemoveOldest())
break; break;
if(!item) if(!item){
item = NEW cacheItem ; try{
item = NEW cacheItem;
}
catch(std::bad_alloc){
SAFE_DELETE(item);
continue;
}
}
if(item && item->Attempt(filename,submode,mError)) if(item && item->Attempt(filename,submode,mError))
break; break;
@@ -1024,14 +1078,29 @@ cacheItem* WCache<cacheItem, cacheActual>::AttemptNew(string filename, int submo
//Worst cache scenerio. Clear every cache we've got. //Worst cache scenerio. Clear every cache we've got.
if(!item || !item->isGood()){ if(!item || !item->isGood()){
resources.ClearUnlocked(); resources.ClearUnlocked();
if(!item) item = NEW(cacheItem); if(!item){
try{
item = NEW(cacheItem);
}
catch(std::bad_alloc){
mError = CACHE_ERROR_BAD_ALLOC;
SAFE_DELETE(item);
return NULL;
}
}
item->Attempt(filename,submode,mError); item->Attempt(filename,submode,mError);
} }
} }
if(item && !item->isGood()){ if(item && !item->isGood()){
Delete(item); if(garbage.size() < MAX_CACHE_GARBAGE){
item->Trash();
garbage.push_back(item);
}
else
SAFE_DELETE(item);
mError = CACHE_ERROR_BAD; mError = CACHE_ERROR_BAD;
return NULL;
} }
else else
mError = CACHE_ERROR_NONE; mError = CACHE_ERROR_NONE;
@@ -1194,9 +1263,16 @@ cacheItem * WCache<cacheItem, cacheActual>::Get(string id, int style, int submod
//Space in cache, make new texture //Space in cache, make new texture
item = AttemptNew(id,submode); item = AttemptNew(id,submode);
//Couldn't make new item. //Couldn't make GOOD new item.
if(item && !item->isGood()) if(item && !item->isGood())
Delete(item); {
if(garbage.size() < MAX_CACHE_GARBAGE){
item->Trash();
garbage.push_back(item);
}
else
SAFE_DELETE(item);
}
} }
if(style == RETRIEVE_MANAGE){ if(style == RETRIEVE_MANAGE){
@@ -1216,7 +1292,7 @@ cacheItem * WCache<cacheItem, cacheActual>::Get(string id, int style, int submod
//Succeeded in making a new item. //Succeeded in making a new item.
if(item){ if(item){
unsigned long isize =item->size(); unsigned long isize = item->size();
totalSize += isize; totalSize += isize;
mError = CACHE_ERROR_NONE; mError = CACHE_ERROR_NONE;
@@ -1225,9 +1301,6 @@ cacheItem * WCache<cacheItem, cacheActual>::Get(string id, int style, int submod
cacheSize += isize; cacheSize += isize;
} }
item->lock();
Cleanup(); //Strictly enforce limits.
item->unlock();
return item; return item;
} }
@@ -1272,14 +1345,21 @@ WCache<cacheItem, cacheActual>::~WCache(){
if(!it->second) if(!it->second)
continue; continue;
Delete(it->second); //Delete(it->second);
SAFE_DELETE(it->second);
} }
for(it=managed.begin();it!=managed.end();it++){ for(it=managed.begin();it!=managed.end();it++){
if(!it->second) if(!it->second)
continue; continue;
Delete(it->second); //Delete(it->second);
SAFE_DELETE(it->second);
}
typename vector<cacheItem*>::iterator g;
for(g=garbage.begin();g!=garbage.end();g++){
SAFE_DELETE(*g);
} }
} }
@@ -1346,11 +1426,7 @@ bool WCache<cacheItem, cacheActual>::RemoveItem(cacheItem * item, bool force){
break; break;
} }
if(it != cache.end() && it->second && (force || !it->second->isLocked())){ if(it != cache.end() && it->second && (force || !it->second->isLocked())){
unsigned long isize = it->second->size();
totalSize -= isize;
cacheSize -= isize;
cacheItems--;
#if defined DEBUG_CACHE #if defined DEBUG_CACHE
lastRemoved = it->first; lastRemoved = it->first;
#endif #endif
@@ -1377,7 +1453,7 @@ bool WCache<cacheItem, cacheActual>::UnlinkCache(cacheItem * item){
it->second = NULL; it->second = NULL;
unsigned long isize = item->size(); unsigned long isize = item->size();
cacheSize-=isize; cacheSize -= isize;
cacheItems--; cacheItems--;
cache.erase(it); cache.erase(it);
return true; return true;
@@ -1398,7 +1474,22 @@ bool WCache<cacheItem, cacheActual>::Delete(cacheItem * item){
if(maxCached == 0) if(maxCached == 0)
item->Nullify(); item->Nullify();
SAFE_DELETE(item); unsigned long isize = item->size();
totalSize -= isize;
cacheSize -= isize;
#ifdef DEBUG_CACHE
if(cacheItems == 0)
OutputDebugString("cacheItems out of sync.\n");
#endif
cacheItems--;
if(garbage.size() > MAX_CACHE_GARBAGE)
SAFE_DELETE(item);
else{
item->Trash();
garbage.push_back(item);
}
return true; return true;
} }
@@ -1419,12 +1510,8 @@ bool WCache<cacheItem, cacheActual>::Release(cacheActual* actual){
if(it->second){ if(it->second){
it->second->unlock(); //Release one lock. it->second->unlock(); //Release one lock.
if(it->second->isLocked()) if(it->second->isLocked())
return true; //Still locked, won't delete. return true; //Still locked, won't delete, not technically a failure.
unsigned long isize = it->second->size();
totalSize -= isize;
cacheSize -= isize;
cacheItems--;
#if defined DEBUG_CACHE #if defined DEBUG_CACHE
lastReleased = it->first; lastReleased = it->first;
#endif #endif