Skip to content

Commit

Permalink
Merge pull request Arakne#333 from vincent4vx/chore-optimisations
Browse files Browse the repository at this point in the history
chore: Optimise allocation on PlayerSprite
  • Loading branch information
vincent4vx authored Feb 15, 2024
2 parents af13003 + ef33778 commit 9efea57
Show file tree
Hide file tree
Showing 34 changed files with 325 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public CharacterAccessories(Collection<PlayerItem> items) {
public Accessory get(AccessoryType type) {
final Accessory accessory = accessories.get(type);

return accessory != null ? accessory : new NullAccessory(type);
return accessory != null ? accessory : NullAccessory.from(type);
}

private void set(Accessory accessory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@
package fr.quatrevieux.araknemu.game.exploration.sprite;

import fr.arakne.utils.maps.constant.Direction;
import fr.arakne.utils.value.Colors;
import fr.arakne.utils.value.constant.Gender;
import fr.arakne.utils.value.constant.Race;
import fr.quatrevieux.araknemu.game.exploration.ExplorationPlayer;
import fr.quatrevieux.araknemu.game.player.sprite.SpriteSize;
import fr.quatrevieux.araknemu.game.world.creature.Sprite;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
* Sprite for exploration player
Expand All @@ -33,6 +38,17 @@
public final class PlayerSprite implements Sprite {
private final ExplorationPlayer exploration;

/**
* Cached constant part of the sprite
* The integrity of this field is ensured by the constantPartHash field
*/
private @Nullable String constantPart = null;

/**
* Store a hash code of the last computed constant part
*/
private int constPartHash = 0;

public PlayerSprite(ExplorationPlayer exploration) {
this.exploration = exploration;
}
Expand Down Expand Up @@ -75,19 +91,56 @@ public String toString() {
return
cell() + ";" +
orientation().ordinal() + ";" +
"0;" + // bonus
id() + ";" +
name() + ";" +
exploration.player().spriteInfo().race().ordinal() + ";" + // @todo title
gfxId() + "^" + exploration.player().spriteInfo().size() + ";" +
exploration.player().spriteInfo().gender().ordinal() + ";" +
constantPart()
;
}

/**
* Get the part of the sprite which change rarely
* This value is cached to avoid recomputation and allocation
*/
private String constantPart() {
final int id = id();
final String name = name();
final Race race = exploration.player().spriteInfo().race();
final int gfxId = gfxId();
final SpriteSize size = exploration.player().spriteInfo().size();
final Gender gender = exploration.player().spriteInfo().gender();
final Colors colors = exploration.player().spriteInfo().colors();
final String accessories = exploration.player().spriteInfo().accessories().toString();
final int restrictions = exploration.restrictions().toInt();
final String lastResult = constantPart;

int newHash = 17 * id;

newHash = 31 * newHash + name.hashCode();
newHash = 31 * newHash + race.hashCode();
newHash = 31 * newHash + gfxId;
newHash = 31 * newHash + size.hashCode();
newHash = 31 * newHash + gender.hashCode();
newHash = 31 * newHash + colors.hashCode();
newHash = 31 * newHash + accessories.hashCode();
newHash = 31 * newHash + restrictions;

if (lastResult != null && newHash == constPartHash) {
return lastResult;
}

constPartHash = newHash;

return constantPart = "0;" + // bonus
id + ";" +
name + ";" +
race.ordinal() + ";" + // @todo title
gfxId + "^" + size + ";" +
gender.ordinal() + ";" +
";" + // @todo alignment
exploration.player().spriteInfo().colors().toHexString(";") + ";" +
exploration.player().spriteInfo().accessories() + ";" +
colors.toHexString(";") + ";" +
accessories + ";" +
";" + // @todo aura
";;" + // @todo emote; emote timer
";;" + // @todo guild; guild emblem
Integer.toString(exploration.restrictions().toInt(), 36) + ";"
Integer.toString(restrictions, 36) + ";"
// @todo mount
;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public Collection<F> targets() {
}

@Override
public Set<C> cells() {
public List<C> cells() {
return effect.area().resolve(target, from);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,6 @@ public static interface EffectScope<F extends FighterData, C extends Battlefield
/**
* Get list of cells into the effect area
*/
public Set<C> cells();
public List<C> cells();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import fr.quatrevieux.araknemu.game.fight.map.FightCell;

import java.util.Collection;
import java.util.Set;
import java.util.List;

/**
* Reveal all invisible objects and fighters
Expand Down Expand Up @@ -61,7 +61,7 @@ private void revealFighters(Fighter caster, Collection<Fighter> targets) {
}

private void revealObjects(Fighter caster, FightCastScope.EffectScope effect) {
final Set<FightCell> cells = effect.cells();
final List<FightCell> cells = effect.cells();

for (BattlefieldObject object : fight.map().objects()) {
if (cells.contains(object.cell()) && !object.visible(caster)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public InventoryAccessories(InventorySlots slots) {
public Accessory get(AccessoryType type) {
return slots.get(type.slot()).entry()
.<Accessory>map(InventoryAccessory::new)
.orElseGet(() -> new NullAccessory(type))
.orElseGet(() -> NullAccessory.from(type))
;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public int gfxId() {

@Override
public SpriteSize size() {
return new SpriteSize(100, 100);
return SpriteSize.DEFAULT;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@

package fr.quatrevieux.araknemu.game.player.sprite;

import org.checkerframework.checker.nullness.qual.Nullable;

/**
* Store size of the sprite
*/
public final class SpriteSize {
public static final SpriteSize DEFAULT = new SpriteSize(100, 100);

private final int x;
private final int y;
private @Nullable String stringCache = null;

public SpriteSize(int x, int y) {
this.x = x;
Expand All @@ -41,6 +46,32 @@ public int y() {

@Override
public String toString() {
return x + "x" + y;
final String stringCache = this.stringCache;

if (stringCache != null) {
return stringCache;
}

return this.stringCache = x + "x" + y;
}

@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}

if (o == null || getClass() != o.getClass()) {
return false;
}

final SpriteSize that = (SpriteSize) o;

return x == that.x && y == that.y;
}

@Override
public int hashCode() {
return (17 + x) * 31 + y;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import org.checkerframework.checker.index.qual.NonNegative;

import java.util.Collections;
import java.util.Set;
import java.util.List;

/**
* Resolve single cell
Expand All @@ -33,8 +33,8 @@ public final class CellArea implements SpellEffectArea {
public static final CellArea INSTANCE = new CellArea();

@Override
public <C extends MapCell> Set<C> resolve(C target, C source) {
return Collections.singleton(target);
public <C extends MapCell> List<C> resolve(C target, C source) {
return Collections.singletonList(target);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import fr.quatrevieux.araknemu.data.value.EffectArea;
import org.checkerframework.checker.index.qual.NonNegative;

import java.util.Set;
import java.util.List;

/**
* Resolve ring area (circle border)
Expand All @@ -38,7 +38,7 @@ public CheckboardArea(EffectArea area) {
}

@Override
public <C extends MapCell> Set<C> resolve(C target, C source) {
public <C extends MapCell> List<C> resolve(C target, C source) {
return area.resolve(target, source);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import org.checkerframework.checker.index.qual.NonNegative;

import java.util.Collections;
import java.util.Set;
import java.util.List;

/**
* Resolve circle area
Expand All @@ -37,12 +37,12 @@ public CircleArea(EffectArea area) {
}

@Override
public <C extends MapCell> Set<C> resolve(C target, C source) {
public <C extends MapCell> List<C> resolve(C target, C source) {
final @NonNegative int size = area.size();

switch (size) {
case 0:
return Collections.singleton(target);
return Collections.singletonList(target);

case 1:
return Util.resolveCenterAndAdjacent(target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
import fr.quatrevieux.araknemu.data.value.EffectArea;
import org.checkerframework.checker.index.qual.NonNegative;

import java.util.Set;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
Expand All @@ -41,10 +42,11 @@ public CircularArea(EffectArea area, Predicate<Integer> distanceChecker) {
}

@Override
public <C extends MapCell> Set<C> resolve(C target, C source) {
@SuppressWarnings("unchecked")
public <C extends MapCell> List<C> resolve(C target, C source) {
final DofusMap<C> map = target.map();
final CoordinateCell<C> center = target.coordinate();
final Set<C> cells = Util.createOrderedSet(target);
final List<C> cells = new ArrayList<>();

for (int i = 0; i < map.size(); ++i) {
final CoordinateCell<C> cell = map.get(i).coordinate();
Expand All @@ -54,6 +56,8 @@ public <C extends MapCell> Set<C> resolve(C target, C source) {
}
}

Util.sortCells(target, cells);

return cells;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
import fr.quatrevieux.araknemu.data.value.EffectArea;
import org.checkerframework.checker.index.qual.NonNegative;

import java.util.Set;
import java.util.ArrayList;
import java.util.List;

/**
* Resolver for cross area
Expand All @@ -37,13 +38,13 @@ public CrossArea(EffectArea area) {
}

@Override
public <C extends MapCell> Set<C> resolve(C target, C source) {
public <C extends MapCell> List<C> resolve(C target, C source) {
// Optimization for size 1
if (size() == 1) {
return Util.resolveCenterAndAdjacent(target);
}

final Set<C> cells = Util.createOrderedSet(target);
final List<C> cells = new ArrayList<>(size() * 4 + 1);

cells.add(target);

Expand All @@ -55,6 +56,8 @@ public <C extends MapCell> Set<C> resolve(C target, C source) {
LineArea.addCells(cells, target, direction, area.size());
}

Util.sortCells(target, cells);

return cells;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
import fr.quatrevieux.araknemu.data.value.EffectArea;
import org.checkerframework.checker.index.qual.NonNegative;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.List;

/**
* Resolve in line area
Expand All @@ -41,13 +41,13 @@ public LineArea(EffectArea area) {
}

@Override
public <C extends MapCell> Set<C> resolve(C target, C source) {
public <C extends MapCell> List<C> resolve(C target, C source) {
if (area.size() == 0) {
return Collections.singleton(target);
return Collections.singletonList(target);
}

final Direction direction = source.coordinate().directionTo(target.coordinate());
final Set<C> cells = new LinkedHashSet<>(area.size() + 1); // Cell are added in order, so no need to sort using a TreeSet
final List<C> cells = new ArrayList<>(area.size() + 1);

cells.add(target);
addCells(cells, target, direction, area.size());
Expand All @@ -65,7 +65,7 @@ public EffectArea.Type type() {
return area.size();
}

static <C extends MapCell<C>> void addCells(Set<C> cells, C start, Direction direction, int size) {
static <C extends MapCell<C>> void addCells(List<C> cells, C start, Direction direction, int size) {
final DofusMap<C> map = start.map();
final int inc = direction.nextCellIncrement(map.dimensions().width());

Expand Down
Loading

0 comments on commit 9efea57

Please sign in to comment.