io.github.spair.byond.dmi.DmiComparator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of byond-dmi-util Show documentation
Show all versions of byond-dmi-util Show documentation
Small set of util classes to work with BYOND dmi files.
package io.github.spair.byond.dmi;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Collections;
import java.util.stream.Collectors;
/**
* Class to compare two {@link io.github.spair.byond.dmi.Dmi} objects and get result of comparison
* as {@link io.github.spair.byond.dmi.DmiDiff}.
*/
@SuppressWarnings("WeakerAccess")
public final class DmiComparator {
/**
* Compares two {@link io.github.spair.byond.dmi.Dmi} objects. One of argument may be null,
* which will be interpreted as if another Dmi created if null is the first parameter or deleted if vice versa.
*
* @param oldDmi old {@link io.github.spair.byond.dmi.Dmi} object or null
* @param newDmi new {@link io.github.spair.byond.dmi.Dmi} object or null
* @return {@link io.github.spair.byond.dmi.DmiDiff} object
*/
@Nonnull
public static DmiDiff compare(@Nullable final Dmi oldDmi, @Nullable final Dmi newDmi) {
DmiDiff dmiDiff = new DmiDiff(getDiffList(oldDmi, newDmi));
dmiDiff.setOldMeta(CheckSupplierUtil.returnIfNonNull(oldDmi, Dmi::getMetadata));
dmiDiff.setNewMeta(CheckSupplierUtil.returnIfNonNull(newDmi, Dmi::getMetadata));
return dmiDiff;
}
private static List getDiffList(@Nullable final Dmi oldDmi, @Nullable final Dmi newDmi) {
List diffEntries = new ArrayList<>();
final Map oldStates = extractStates(oldDmi);
final Map newStates = extractStates(newDmi);
oldStates.forEach((stateName, oldState) -> {
final DmiState newState = newStates.get(stateName);
if (newState != null) {
diffEntries.addAll(findOldAndNewStateDiff(oldState, newState));
} else {
diffEntries.addAll(listOnlyOneStateSprites(oldState, true));
}
});
newStates.forEach((stateName, newState) -> {
if (!oldStates.containsKey(stateName)) {
diffEntries.addAll(listOnlyOneStateSprites(newState, false));
}
});
return diffEntries;
}
private static List listOnlyOneStateSprites(final DmiState state, final boolean isOldState) {
List diffs = new ArrayList<>();
final String stateName = state.getMeta().getName();
state.getSprites().forEach((spriteDir, stateSprite) ->
stateSprite.forEach(sprite -> {
if (isOldState) {
diffs.add(new Diff(stateName, sprite, null));
} else {
diffs.add(new Diff(stateName, null, sprite));
}
})
);
return diffs;
}
private static List findOldAndNewStateDiff(final DmiState oldState, final DmiState newState) {
List diffs = new ArrayList<>();
final String stateName = oldState.getMeta().getName();
final Map> oldStateSprites = oldState.getSprites();
final Map> newStateSprites = newState.getSprites();
oldStateSprites.forEach((spriteDir, oldSprites) -> {
final List newSprites = newStateSprites.getOrDefault(spriteDir, Collections.emptyList());
final int oldSpritesCount = oldSprites.size();
final int newSpritesCount = newSprites.size();
for (int frameNumber = 0; frameNumber < oldSpritesCount; frameNumber++) {
DmiSprite oldSprite = oldSprites.get(frameNumber);
DmiSprite newSprite = null;
if (frameNumber <= (newSpritesCount - 1)) {
newSprite = newSprites.get(frameNumber);
}
if (!oldSprite.equals(newSprite)) {
diffs.add(new Diff(stateName, oldSprite, newSprite));
}
}
if (oldSpritesCount < newSpritesCount) {
for (int frameNumber = oldSpritesCount; frameNumber < newSpritesCount; frameNumber++) {
diffs.add(new Diff(stateName, null, newSprites.get(frameNumber)));
}
}
});
final int oldDirsCount = oldStateSprites.size();
final int newDirsCount = newStateSprites.size();
if (oldDirsCount < newDirsCount) {
newStateSprites.keySet()
.stream().filter(d -> !oldStateSprites.keySet().contains(d)).collect(Collectors.toSet())
.forEach(spriteDir ->
newStateSprites.get(spriteDir).forEach(newSprite ->
diffs.add(new Diff(stateName, null, newSprite))
)
);
}
return diffs;
}
private static Map extractStates(final Dmi dmi) {
return Optional
.ofNullable(
CheckSupplierUtil.returnIfNonNull(dmi, Dmi::getStates)
).orElse(Collections.emptyMap());
}
private DmiComparator() {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy