Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Optimise allocation on PlayerSprite #333

Merged
merged 1 commit into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading