mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-07-04 15:27:30 +07:00
Removed requirement for AttributesUpdater to be stateful
Used a clever trick on StatList.StatIterator, where read stats can be pushed onto the list starting from the front. The result is a sorted list not containing elements which were not added back.
This commit is contained in:
@ -10,7 +10,6 @@ public final class AttributesUpdater {
|
||||
private static final Logger log = LogManager.getLogger(AttributesUpdater.class);
|
||||
|
||||
private final UpdateSequence SEQUENCER = new UpdateSequence(this);
|
||||
private final StatList cache = StatList.obtainLarge(); // easier than implementing StatList#remove
|
||||
|
||||
public UpdateSequence update(final Attributes attrs, final CharStats.Entry charStats) {
|
||||
return update(attrs, attrs, charStats);
|
||||
@ -76,34 +75,31 @@ public final class AttributesUpdater {
|
||||
final StatListGetter rem,
|
||||
final Attributes opBase,
|
||||
final CharStats.Entry charStats) {
|
||||
// should pass values from rem to agg if applicable
|
||||
final StatListBuilder cache = this.cache.clear().buildList();
|
||||
for (StatGetter stat : rem) {
|
||||
for (final StatList.StatIterator it = rem.statIterator(); it.hasNext();) {
|
||||
final StatGetter stat = it.next();
|
||||
final ItemStatCost.Entry entry = stat.entry();
|
||||
try {
|
||||
MDC.put("applyStat", stat.id());
|
||||
final int op = entry.op;
|
||||
if (op > 0) {
|
||||
if (log.traceEnabled()) log.trace("Applying stat({}) op({})", stat.debugString(), op);
|
||||
op(agg, cache, opBase, charStats, stat);
|
||||
op(agg, it, opBase, charStats, stat);
|
||||
} else if (base.contains(stat)) {
|
||||
if (log.traceEnabled()) log.trace("Aggregating stat({})", stat.debugString());
|
||||
agg.add(stat);
|
||||
} else {
|
||||
if (log.traceEnabled()) log.trace("Propagating stat({})", stat.debugString());
|
||||
cache.add(stat);
|
||||
it.pushback();
|
||||
}
|
||||
} finally {
|
||||
MDC.remove("applyStat");
|
||||
}
|
||||
}
|
||||
|
||||
rem.parent().setAll(cache.build());
|
||||
}
|
||||
|
||||
static void op(
|
||||
final StatListBuilder agg,
|
||||
final StatListBuilder rem,
|
||||
final StatList.StatIterator it,
|
||||
final Attributes opBase,
|
||||
final CharStats.Entry charStats,
|
||||
final StatGetter stat) {
|
||||
@ -133,7 +129,7 @@ public final class AttributesUpdater {
|
||||
}
|
||||
|
||||
if (ops == 0) {
|
||||
rem.add(stat);
|
||||
it.pushback();
|
||||
} else if (ops < expectedOps) {
|
||||
log.warn("{} stats were not op'd", ops);
|
||||
}
|
||||
|
@ -736,11 +736,14 @@ public final class StatList {
|
||||
|
||||
public final class StatIterator implements Iterator<StatGetter> {
|
||||
final StatGetter stat = new StatGetter(StatList.this);
|
||||
int list; /** used for {@link #pushback} */
|
||||
int head; /** used for {@link #pushback} */
|
||||
int index;
|
||||
int endIndex;
|
||||
|
||||
StatIterator reset(final int list) {
|
||||
index = startingOffset(list);
|
||||
this.list = list;
|
||||
head = index = startingOffset(list);
|
||||
endIndex = endingOffset(list);
|
||||
return this;
|
||||
}
|
||||
@ -755,6 +758,18 @@ public final class StatList {
|
||||
return stat.update(index++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recycles the previously read stat by re-adding it onto a new list being
|
||||
* formed at the start of this list while iteration is occurring. This
|
||||
* method effectively breaks the old list and shrinks it to a subset of
|
||||
* entries.
|
||||
*/
|
||||
void pushback() {
|
||||
assert head < index : "head(" + head + ") cannot pass index(" + index + ")";
|
||||
StatList.this.set(head++, stat.id(), stat.param(), stat.value(), stat.entry());
|
||||
setEndingOffset(list, head);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
Reference in New Issue
Block a user