Skip to content

Commit

Permalink
Add first config options
Browse files Browse the repository at this point in the history
Signed-off-by: roadhog360 <[email protected]>
  • Loading branch information
Roadhog360 committed Sep 6, 2024
1 parent e687835 commit ab4404b
Show file tree
Hide file tree
Showing 8 changed files with 302 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package roadhog360.simpleskinbackport.configuration;

import cpw.mods.fml.client.event.ConfigChangedEvent;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.launchwrapper.Launch;
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import org.apache.commons.lang3.ArrayUtils;
import org.spongepowered.asm.mixin.MixinEnvironment;
import roadhog360.simpleskinbackport.SimpleSkinBackport;
import roadhog360.simpleskinbackport.configuration.configs.ConfigMain;
import roadhog360.simpleskinbackport.configuration.configs.ConfigModCompat;
import roadhog360.simpleskinbackport.core.DefaultPlayerSkin;
import roadhog360.simpleskinbackport.mixinplugin.SimpleSkinBackportEarlyMixins;

import java.io.File;
import java.util.*;

public abstract class ConfigBase extends Configuration {
protected final List<ConfigCategory> configCats = new ArrayList<>();
private static final Set<ConfigBase> CONFIGS = new HashSet<>();

public static final String configDir = "config" + File.separator + SimpleSkinBackport.MODID + File.separator;

public static final ConfigBase MAIN = new ConfigMain(createConfigFile("main"));
public static final ConfigBase MOD_COMPAT = new ConfigModCompat(createConfigFile("modcompat"));

public ConfigBase(File file) {
super(file);
CONFIGS.add(this);
}

private static File createConfigFile(String name) {
return new File(Launch.minecraftHome, configDir + name + ".cfg");
}

public static void initializeConfigs() {
for (ConfigBase config : CONFIGS) {
config.syncConfig();
}
}

private void syncConfig() {
syncConfigOptions();

for (ConfigCategory cat : configCats) {
if (SimpleSkinBackportEarlyMixins.SIDE == MixinEnvironment.Side.SERVER) {
if (cat.getName().toLowerCase().contains("client")) {
for (Property prop : cat.getOrderedValues()) {
cat.remove(prop.getName());
}
}
}

if (cat.isEmpty() && !cat.getName().toLowerCase().contains("experiment")) {
removeCategory(cat);
}
}

if (hasChanged()) {
save();
}
}

protected abstract void syncConfigOptions();

/**
* Used in case we need to wait till later to initialize some config values.
*/
protected void initValues() {
}

public static void postInit() {
for (ConfigBase config : CONFIGS) {
config.initValues();
}
}

@SubscribeEvent
public void onConfigChanged(ConfigChangedEvent.OnConfigChangedEvent eventArgs) {
if (SimpleSkinBackport.MODID.equals(eventArgs.modID))
syncConfig();
}

protected static String[] getSkinReplacementModes(boolean isNoneAllowed) {
String[] array = new String[0];
if(isNoneAllowed) {
ArrayUtils.add(array, "NONE");
}
Arrays.stream(DefaultPlayerSkin.Set.values()).forEachOrdered(mode -> ArrayUtils.add(array, mode.name()));
return array;
}

protected static String getSkinReplacementDescriptions() {
StringBuilder sb = new StringBuilder();
DefaultPlayerSkin.Set[] values = DefaultPlayerSkin.Set.values();
for (int i = 0, valuesLength = values.length; i < valuesLength; i++) {
DefaultPlayerSkin.Set skinSet = values[i];
sb.append(skinSet.name()).append(": ").append(skinSet.getDescription());
if(i < valuesLength - 1) {
sb.append("\n");
}
}
return sb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package roadhog360.simpleskinbackport.configuration.configs;

import roadhog360.simpleskinbackport.configuration.ConfigBase;
import roadhog360.simpleskinbackport.core.DefaultPlayerSkin;

import java.io.File;

public class ConfigMain extends ConfigBase {

public static DefaultPlayerSkin.Set defaultSkinSet;

static final String catSkins = "skins";
static final String catHeads = "skins";

public ConfigMain(File file) {
super(file);

getCategory(catSkins).setComment("Settings for mod-specific patches.");

configCats.add(getCategory(catSkins));
}

@Override
protected void syncConfigOptions() {
defaultSkinSet = DefaultPlayerSkin.Set.valueOf(
getString("defaultSkinSet", catSkins, DefaultPlayerSkin.Set.ALL_DEFAULTS.name(),
"""
What default skin set should we use for players? This only affects players whose skins are not loaded, or do not have a custom skin.
Note that players may also set their skin to one of the new defaults in their Minecraft launcher, and that will take precedent over this option.
Each set contains the following skins:
""" + ConfigBase.getSkinReplacementDescriptions(), ConfigBase.getSkinReplacementModes(false))
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package roadhog360.simpleskinbackport.configuration.configs;

import roadhog360.simpleskinbackport.configuration.ConfigBase;
import roadhog360.simpleskinbackport.core.DefaultPlayerSkin;

import java.io.File;

public class ConfigModCompat extends ConfigBase {

public static DefaultPlayerSkin.Set TFgiantSkinSet;

static final String catMisc = "misc";

public ConfigModCompat(File file) {
super(file);

getCategory(catMisc).setComment("Settings for mod-specific patches.");

configCats.add(getCategory(catMisc));
}


//TODO: Move Iron Chest checks here
@Override
protected void syncConfigOptions() {
TFgiantSkinSet = DefaultPlayerSkin.Set.valueOfOrNull(
getString("TwilightForest:giantSkinSet", catMisc, DefaultPlayerSkin.NONE,
"""
What default skin set should we use for Twilight Forest giants? NONE means they copy the client player's skin and arms
The other values set a skin randomly assigned based on the Giant's UUID. See the main config for more info on these.""", ConfigBase.getSkinReplacementModes(true))
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package roadhog360.simpleskinbackport.core;

import com.google.common.collect.Lists;
import net.minecraft.util.ResourceLocation;
import org.apache.commons.lang3.tuple.Pair;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;

public class DefaultPlayerSkin {
private static final ResourceLocation[] DEFAULT_SKINS = new ResourceLocation[] {
new ResourceLocation("textures/entity/player/slim/alex.png"),
new ResourceLocation("textures/entity/player/slim/ari.png"),
new ResourceLocation("textures/entity/player/slim/efe.png"),
new ResourceLocation("textures/entity/player/slim/kai.png"),
new ResourceLocation("textures/entity/player/slim/makena.png"),
new ResourceLocation("textures/entity/player/slim/noor.png"),
new ResourceLocation("textures/entity/player/slim/steve.png"),
new ResourceLocation("textures/entity/player/slim/sunny.png"),
new ResourceLocation("textures/entity/player/slim/zuri.png"),

new ResourceLocation("textures/entity/player/wide/alex.png"),
new ResourceLocation("textures/entity/player/wide/ari.png"),
new ResourceLocation("textures/entity/player/wide/efe.png"),
new ResourceLocation("textures/entity/player/wide/kai.png"),
new ResourceLocation("textures/entity/player/wide/makena.png"),
new ResourceLocation("textures/entity/player/wide/noor.png"),
new ResourceLocation("textures/entity/player/wide/steve.png"),
new ResourceLocation("textures/entity/player/wide/sunny.png"),
new ResourceLocation("textures/entity/player/wide/zuri.png")};

public static final ResourceLocation ALEX = DEFAULT_SKINS[0];
public static final ResourceLocation STEVE = DEFAULT_SKINS[15];

public static final UUID NULL_UUID = UUID.randomUUID(); //Used if the UUID passed in is somehow null.

public static final String NONE = "NONE";

public enum Set {
STEVE_ONLY("The only default skin will be Steve, the tried-and-true classic player model. His arms will always be wide.", STEVE),
STEVE_ALEX("The default skins will either be wide-armed Steve or slim-armed Alex, as it was in 1.8 to 1.19.2.", STEVE, ALEX),
ALL_DEFAULTS("Steve, Alex, and all of the new 1.19.3 default skins will be assigned. They all can appear in slim or wide armed variants.", DEFAULT_SKINS),
// BONUS_CHARACTERS, //Some of the alternate skins from the old legacy console default skin packs. Currently not implemented
;

private final List<Pair<ResourceLocation, Boolean>> skins = Lists.newLinkedList();
private final String description;

Set(String description, ResourceLocation... locs) {
this.description = description;
for(ResourceLocation location : locs) {
skins.add(Pair.of(location, location.toString().contains("slim")));
}
}

public ResourceLocation getDefaultSkin(int index) {
return getEntryFromIndex(index).getLeft();
}

public ResourceLocation getDefaultSkin(UUID uuid) {
return getDefaultSkin(uuid.hashCode());
}

public boolean isDefaultSkinSlim(int index) {
return getEntryFromIndex(index).getRight();
}

public boolean isDefaultSkinSlim(UUID uuid) {
return isDefaultSkinSlim(uuid.hashCode());
}

private Pair<ResourceLocation, Boolean> getEntryFromIndex(int index) {
if(skins.isEmpty()) {
throw new RuntimeException("Default skin set " + name() + " had empty skin list. What are you doing!?");
}
if(skins.size() == 1) {
return skins.get(0);
}
if(skins.size() == 2) {
return skins.get(index & 1);//1.8 skin choosing logic, returns Alex if UUID hash & 1 == 1
}
return skins.get(Math.floorMod(index, skins.size()));//1.19+ skin choosing logic. Uses Math.floorMod to roll the index of skin based on UUID hash
}

public String getDescription() {
return description;
}

public static Set valueOfOrNull(String value) {
return Arrays.stream(Set.values()).filter(skinSet -> skinSet.name().equals(value)).findFirst().orElse(null);
}
}
}
48 changes: 0 additions & 48 deletions src/main/java/roadhog360/simpleskinbackport/core/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,63 +12,15 @@
import net.minecraft.client.resources.SkinManager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
import roadhog360.simpleskinbackport.ducks.IArmsState;
import roadhog360.simpleskinbackport.ducks.ITransparentBox;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

public class Utils {
private static final ResourceLocation[] DEFAULT_SKINS = new ResourceLocation[] {
new ResourceLocation("textures/entity/player/slim/alex.png"),
new ResourceLocation("textures/entity/player/slim/ari.png"),
new ResourceLocation("textures/entity/player/slim/efe.png"),
new ResourceLocation("textures/entity/player/slim/kai.png"),
new ResourceLocation("textures/entity/player/slim/makena.png"),
new ResourceLocation("textures/entity/player/slim/noor.png"),
new ResourceLocation("textures/entity/player/slim/steve.png"),
new ResourceLocation("textures/entity/player/slim/sunny.png"),
new ResourceLocation("textures/entity/player/slim/zuri.png"),

new ResourceLocation("textures/entity/player/wide/alex.png"),
new ResourceLocation("textures/entity/player/wide/ari.png"),
new ResourceLocation("textures/entity/player/wide/efe.png"),
new ResourceLocation("textures/entity/player/wide/kai.png"),
new ResourceLocation("textures/entity/player/wide/makena.png"),
new ResourceLocation("textures/entity/player/wide/noor.png"),
new ResourceLocation("textures/entity/player/wide/steve.png"),
new ResourceLocation("textures/entity/player/wide/sunny.png"),
new ResourceLocation("textures/entity/player/wide/zuri.png")};

public static final ResourceLocation STEVE = DEFAULT_SKINS[15];
public static final ResourceLocation ALEX = DEFAULT_SKINS[0];

public static int getIndexFromUUID(UUID uuid) {
if(uuid == null) { //TODO Config to not use new skins perhaps?
return 15;
}
return Math.floorMod(uuid.hashCode(), DEFAULT_SKINS.length);
}

public static ResourceLocation getDefaultSkin(int index) {
return DEFAULT_SKINS[index % DEFAULT_SKINS.length];
}

public static ResourceLocation getDefaultSkin(UUID uuid) {
return getDefaultSkin(getIndexFromUUID(uuid));
}

public static boolean isDefaultSkinSlim(int index) {
return index % DEFAULT_SKINS.length < DEFAULT_SKINS.length / 2;
}

public static boolean isDefaultSkinSlim(UUID uuid) {
return isDefaultSkinSlim(getIndexFromUUID(uuid));
}

public static boolean getSlimFromBase64Data(String base64) {
JsonObject props = new Gson().fromJson(new String(Base64.getDecoder().decode(base64), StandardCharsets.UTF_8), JsonObject.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import org.spongepowered.asm.mixin.MixinEnvironment;
import roadhog360.simpleskinbackport.configuration.ConfigBase;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -20,6 +21,12 @@ public String getMixinConfig() {

@Override
public List<String> getMixins(Set<String> loadedCoreMods) {
try {
ConfigBase.initializeConfigs();
} catch (Exception e) {
throw new RuntimeException("Configs failed to load!", e);
}

List<String> mixins = new ArrayList<>();
mixins.add("MixinEntityPlayer");
if (SIDE == MixinEnvironment.Side.CLIENT) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import roadhog360.simpleskinbackport.core.Utils;
import roadhog360.simpleskinbackport.configuration.configs.ConfigMain;
import roadhog360.simpleskinbackport.ducks.IArmsState;

@Mixin(AbstractClientPlayer.class)
Expand All @@ -23,13 +23,13 @@ public MixinAbstractClientPlayer(World p_i45324_1_, GameProfile p_i45324_2_) {

@Inject(method = "<init>", at = @At(value = "TAIL"))
private void setDefaultSkinState(World p_i45074_1_, GameProfile p_i45074_2_, CallbackInfo ci) {
simpleSkinBackport$setSlim(Utils.isDefaultSkinSlim(getPersistentID()));
simpleSkinBackport$setSlim(ConfigMain.defaultSkinSet.isDefaultSkinSlim(getPersistentID()));
}

@Redirect(method = "getLocationSkin()Lnet/minecraft/util/ResourceLocation;",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/entity/AbstractClientPlayer;locationStevePng:Lnet/minecraft/util/ResourceLocation;"))
private ResourceLocation setNewDefaultSkinBehavior() {
return Utils.getDefaultSkin(getPersistentID());
return ConfigMain.defaultSkinSet.getDefaultSkin(getPersistentID());
}

// UUID uuid = UUID.randomUUID();
Expand All @@ -42,9 +42,11 @@ private ResourceLocation setNewDefaultSkinBehavior() {
// @WrapOperation(method = "getLocationSkin()Lnet/minecraft/util/ResourceLocation;",
// at = @At(value = "FIELD", target = "Lnet/minecraft/client/entity/AbstractClientPlayer;locationSkin:Lnet/minecraft/util/ResourceLocation;", ordinal = 1))
// private ResourceLocation setNewSkinModel(AbstractClientPlayer instance, Operation<ResourceLocation> original) {
// boolean slim = Utils.isDefaultSkinSlim(uuid);
// ResourceLocation skin = Utils.getDefaultSkin(uuid);
// simpleSkinBackport$setSlim(slim);
// return skin;
//// boolean slim = Utils.isDefaultSkinSlim(uuid);
//// ResourceLocation skin = Utils.getDefaultSkin(uuid);
//// simpleSkinBackport$setSlim(slim);
//// return skin;
// simpleSkinBackport$setSlim(ConfigMain.defaultSkinSet.isDefaultSkinSlim(getPersistentID()));
// return ConfigMain.defaultSkinSet.getDefaultSkin(getPersistentID());
// }
}
Loading

0 comments on commit ab4404b

Please sign in to comment.