Skip to content

Commit

Permalink
wip: Begin implementation of cost modifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
BlayTheNinth committed Dec 22, 2023
1 parent f097684 commit bf6198a
Show file tree
Hide file tree
Showing 14 changed files with 313 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@

import net.blay09.mods.waystones.xp.ExperienceLevelCost;
import net.blay09.mods.waystones.xp.ExperiencePointsCost;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Player;

import java.util.List;

public interface ExperienceCost {
boolean canAfford(Player player);

void consume(Player player);

int getCostAsLevels(Player player);

Component getCostAsTooltip(Player player);
void appendHoverText(Player player, List<Component> tooltip);

boolean isEmpty();

Expand Down Expand Up @@ -42,8 +45,8 @@ public int getCostAsLevels(Player player) {
}

@Override
public Component getCostAsTooltip(Player player) {
return Component.translatable("gui.waystones.waystone_selection.no_xp_requirement");
public void appendHoverText(Player player, List<Component> tooltip) {
tooltip.add(Component.translatable("gui.waystones.waystone_selection.no_xp_requirement"));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,7 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float

if (isHovered && mouseX <= getX() + 16) {
final List<Component> tooltip = new ArrayList<>();
final var xpCostText = xpCost.getCostAsTooltip(mc.player);
if (xpCostText instanceof MutableComponent mutableComponent) {
mutableComponent.withStyle(canAfford ? ChatFormatting.GREEN : ChatFormatting.RED);
}
tooltip.add(xpCostText);
xpCost.appendHoverText(mc.player, tooltip);
guiGraphics.renderTooltip(mc.font, tooltip, Optional.empty(), mouseX, mouseY + mc.font.lineHeight);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,29 @@ public enum TransportPets {
DISABLED
}

public XpCost xpCost = new XpCost();
public Costs costs = new Costs();
public Restrictions restrictions = new Restrictions();
public Cooldowns cooldowns = new Cooldowns();
public InventoryButton inventoryButton = new InventoryButton();
public WorldGen worldGen = new WorldGen();
public Client client = new Client();
public Compatibility compatibility = new Compatibility();

public static class XpCost {
public static class Costs {
@Synced
@Comment("Set to false to simply disable all xp costs.")
public boolean enableCosts = true;

@Synced
@Comment("Set to false to simply disable all xp costs.")
public List<String> costModifiers = List.of(
"waystones:distance_add_xp(0.01)",
"waystones:source_multiply_xp(waystone:warp_plate, 0)",
"waystones:target_multiply_xp(waystone:global_waystone, 0)",
"waystones:dimensional_add_xp(27)",
"waystones:min_xp(0)",
"waystones:max_xp(27)");

@Synced
@Comment("Set to true if experience cost should cost full levels rather than experience points. Make sure to also adjust blocksPerXpLevel, maximumBaseXpCost and dimensionalWarpXpCost appropriately.")
public boolean xpCostsFullLevels = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
*/
@Deprecated(forRemoval = true)
public enum WarpMode {
INVENTORY_BUTTON(() -> WaystonesConfig.getActive().xpCost.inventoryButtonXpCostMultiplier, false),
INVENTORY_BUTTON(() -> WaystonesConfig.getActive().costs.inventoryButtonXpCostMultiplier, false),
WARP_SCROLL(() -> 0.0, true),
RETURN_SCROLL(() -> 0.0, true),
WARP_STONE(() -> WaystonesConfig.getActive().xpCost.warpStoneXpCostMultiplier, false),
WAYSTONE_TO_WAYSTONE(() -> WaystonesConfig.getActive().xpCost.waystoneXpCostMultiplier, false),
SHARESTONE_TO_SHARESTONE(() -> WaystonesConfig.getActive().xpCost.sharestoneXpCostMultiplier, false),
WARP_PLATE(() -> WaystonesConfig.getActive().xpCost.warpPlateXpCostMultiplier, false),
PORTSTONE_TO_WAYSTONE(() -> WaystonesConfig.getActive().xpCost.portstoneXpCostMultiplier, false),
WARP_STONE(() -> WaystonesConfig.getActive().costs.warpStoneXpCostMultiplier, false),
WAYSTONE_TO_WAYSTONE(() -> WaystonesConfig.getActive().costs.waystoneXpCostMultiplier, false),
SHARESTONE_TO_SHARESTONE(() -> WaystonesConfig.getActive().costs.sharestoneXpCostMultiplier, false),
WARP_PLATE(() -> WaystonesConfig.getActive().costs.warpPlateXpCostMultiplier, false),
PORTSTONE_TO_WAYSTONE(() -> WaystonesConfig.getActive().costs.portstoneXpCostMultiplier, false),
CUSTOM(() -> 0.0, false);

public static WarpMode[] values = values();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static ExperienceCost predictExperienceLevelCost(Entity player, IWaystone

public static ExperienceCost getExperienceLevelCost(IWaystoneTeleportContext context) {
final var xpCost = getExperienceLevelCost(context.getEntity(), context.getTargetWaystone(), context.getWarpMode(), context);
if (WaystonesConfig.getActive().xpCost.xpCostsFullLevels) {
if (WaystonesConfig.getActive().costs.xpCostsFullLevels) {
return ExperienceCost.fromLevels(xpCost);
} else {
return ExperienceCost.fromExperience(xpCost);
Expand All @@ -71,25 +71,25 @@ public static int getExperienceLevelCost(Entity entity, IWaystone waystone, Warp
return 0;
}

int xpForLeashed = WaystonesConfig.getActive().xpCost.xpCostPerLeashed * context.getLeashedEntities().size();
int xpForLeashed = WaystonesConfig.getActive().costs.xpCostPerLeashed * context.getLeashedEntities().size();

double xpCostMultiplier = warpMode.getXpCostMultiplier();
if (waystone.getVisibility() == WaystoneVisibility.GLOBAL) {
xpCostMultiplier *= WaystonesConfig.getActive().xpCost.globalWaystoneXpCostMultiplier;
xpCostMultiplier *= WaystonesConfig.getActive().costs.globalWaystoneXpCostMultiplier;
}

BlockPos pos = waystone.getPos();
double dist = Math.sqrt(player.distanceToSqr(pos.getX(), player.getY(), pos.getZ())); // ignore y distance
final double minimumXpCost = WaystonesConfig.getActive().xpCost.minimumBaseXpCost;
final double maximumXpCost = WaystonesConfig.getActive().xpCost.maximumBaseXpCost;
final double minimumXpCost = WaystonesConfig.getActive().costs.minimumBaseXpCost;
final double maximumXpCost = WaystonesConfig.getActive().costs.maximumBaseXpCost;
double xpLevelCost;
if (waystone.getDimension() != player.level().dimension()) {
int dimensionalWarpXpCost = WaystonesConfig.getActive().xpCost.dimensionalWarpXpCost;
int dimensionalWarpXpCost = WaystonesConfig.getActive().costs.dimensionalWarpXpCost;
xpLevelCost = Mth.clamp(dimensionalWarpXpCost, minimumXpCost, dimensionalWarpXpCost);
} else if (WaystonesConfig.getActive().xpCost.blocksPerXpLevel > 0) {
xpLevelCost = Mth.clamp(Math.floor(dist / (float) WaystonesConfig.getActive().xpCost.blocksPerXpLevel), minimumXpCost, maximumXpCost);
} else if (WaystonesConfig.getActive().costs.blocksPerXpLevel > 0) {
xpLevelCost = Mth.clamp(Math.floor(dist / (float) WaystonesConfig.getActive().costs.blocksPerXpLevel), minimumXpCost, maximumXpCost);

if (WaystonesConfig.getActive().xpCost.inverseXpCost) {
if (WaystonesConfig.getActive().costs.inverseXpCost) {
xpLevelCost = maximumXpCost - xpLevelCost;
}
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.blay09.mods.waystones.cost;

import net.blay09.mods.waystones.api.IWaystoneTeleportContext;
import net.minecraft.resources.ResourceLocation;

import java.util.HashMap;
import java.util.Map;

public class CostContext {

private final Map<ResourceLocation, Object> costInstances = new HashMap<>();
private final IWaystoneTeleportContext context;

public CostContext(IWaystoneTeleportContext context) {
this.context = context;
}

@SuppressWarnings("unchecked")
public <T, P> void apply(CostModifier<T, P> modifier) {
var costInstance = (T) costInstances.get(modifier.getCostType());
if (costInstance == null) {
costInstance = CostRegistry.<T>getCostType(modifier.getCostType()).createInstance();
}
costInstances.put(modifier.getCostType(), modifier.apply(costInstance, this, null));
}

public float getContextValue(ResourceLocation id) {
return switch (id.toString()) {
case "waystones:distance" -> (float) Math.sqrt(context.getEntity().distanceToSqr(context.getDestination().getLocation()));
default -> 0f;
};
}

public boolean matchesCondition(ResourceLocation id) {

return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package net.blay09.mods.waystones.cost;

import net.minecraft.resources.ResourceLocation;

public interface CostModifier<TCost, TParameter> extends CostModifierFunction<TCost, TParameter> {
ResourceLocation getId();

ResourceLocation getCostType();

Class<TParameter> getParameterType();
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package net.blay09.mods.waystones.cost;

public interface CostModifierFunction<TCost, TParameter> {
TCost apply(TCost costInstance, CostContext context, TParameter parameters);
}
148 changes: 148 additions & 0 deletions shared/src/main/java/net/blay09/mods/waystones/cost/CostRegistry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package net.blay09.mods.waystones.cost;

import net.minecraft.resources.ResourceLocation;

import java.util.HashMap;
import java.util.Map;

public class CostRegistry {

private static final Map<ResourceLocation, CostType<?>> costTypes = new HashMap<>();
private static final Map<ResourceLocation, CostModifier<?, ?>> costModifiers = new HashMap<>();

public record IntParameter(int value) {
}

public record FloatParameter(float value) {
}

public record IdParameter(ResourceLocation value) {
}

public record ScaledParameters(IdParameter id, FloatParameter scale) {
}

public record ConditionalParameters(IdParameter id, FloatParameter scale) {
}

public static void registerDefaults() {
final var experiencePoints = new ExperiencePointsCostType();
final var levels = new ExperienceLevelCostType();

register(experiencePoints);
register(levels);

registerModifier("add_levels", levels, FloatParameter.class, (cost, context, parameters) -> {
cost.setLevels((int) (cost.getLevels() + parameters.value));
return cost;
});
registerModifier("conditional_add_levels", levels, ConditionalParameters.class, (cost, context, parameters) -> {
if (context.matchesCondition(parameters.id.value)) {
cost.setLevels((int) (cost.getLevels() + parameters.scale.value));
}
return cost;
});
registerModifier("multiply_levels", levels, FloatParameter.class, (cost, context, parameters) -> {
cost.setLevels((int) (cost.getLevels() * parameters.value));
return cost;
});
registerModifier("conditional_multiply_levels", levels, ConditionalParameters.class, (cost, context, parameters) -> {
if (context.matchesCondition(parameters.id.value)) {
cost.setLevels((int) (cost.getLevels() * parameters.scale.value));
}
return cost;
});
registerModifier("scaled_add_levels", levels, ScaledParameters.class, (cost, context, parameters) -> {
final var sourceValue = context.getContextValue(parameters.id.value);
cost.setLevels((int) (cost.getLevels() + sourceValue * parameters.scale.value));
return cost;
});
registerModifier("multiply_levels", levels, FloatParameter.class, (cost, context, parameters) -> {
cost.setLevels((int) (cost.getLevels() * parameters.value));
return cost;
});
registerModifier("min_levels", levels, IntParameter.class, (cost, context, parameters) -> {
cost.setLevels(Math.max(cost.getLevels(), parameters.value));
return cost;
});
registerModifier("max_levels", levels, IntParameter.class, (cost, context, parameters) -> {
cost.setLevels(Math.min(cost.getLevels(), parameters.value));
return cost;
});

registerModifier("add_xp", experiencePoints, IntParameter.class, (cost, context, parameters) -> {
cost.setPoints(cost.getPoints() + parameters.value);
return cost;
});
registerModifier("conditional_add_xp", experiencePoints, ConditionalParameters.class, (cost, context, parameters) -> {
if (context.matchesCondition(parameters.id.value)) {
cost.setPoints((int) (cost.getPoints() + parameters.scale.value));
}
return cost;
});
registerModifier("multiply_xp", experiencePoints, FloatParameter.class, (cost, context, parameters) -> {
cost.setPoints((int) (cost.getPoints() * parameters.value));
return cost;
});
registerModifier("conditional_multiply_xp", experiencePoints, ConditionalParameters.class, (cost, context, parameters) -> {
if (context.matchesCondition(parameters.id.value)) {
cost.setPoints((int) (cost.getPoints() * parameters.scale.value));
}
return cost;
});
registerModifier("scaled_add_xp", experiencePoints, ScaledParameters.class, (cost, context, parameters) -> {
final var sourceValue = context.getContextValue(parameters.id.value);
cost.setPoints((int) (cost.getPoints() + sourceValue * parameters.scale.value));
return cost;
});
registerModifier("min_xp", experiencePoints, IntParameter.class, (cost, context, parameters) -> {
cost.setPoints(Math.max(cost.getPoints(), parameters.value));
return cost;
});
registerModifier("max_xp", experiencePoints, IntParameter.class, (cost, context, parameters) -> {
cost.setPoints(Math.min(cost.getPoints(), parameters.value));
return cost;
});
}

public static void register(CostType<?> costType) {
costTypes.put(costType.getId(), costType);
}

public static void register(CostModifier<?, ?> costModifier) {
costModifiers.put(costModifier.getId(), costModifier);
}

private static <T, P> void registerModifier(String name, CostType<T> costType, Class<P> parameterType, CostModifierFunction<T, P> function) {
register(new CostModifier<T, P>() {
@Override
public ResourceLocation getId() {
return new ResourceLocation("waystones", name);
}

@Override
public ResourceLocation getCostType() {
return costType.getId();
}

@Override
public Class<P> getParameterType() {
return parameterType;
}

@Override
public T apply(T cost, CostContext context, P parameters) {
return function.apply(cost, context, parameters);
}
});
}

@SuppressWarnings("unchecked")
public static <T> CostType<T> getCostType(ResourceLocation costType) {
return (CostType<T>) costTypes.get(costType);
}

public static CostModifier<?, ?> getCostModifier(ResourceLocation costModifier) {
return costModifiers.get(costModifier);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package net.blay09.mods.waystones.cost;

import net.minecraft.resources.ResourceLocation;

public interface CostType<T> {
ResourceLocation getId();
T createInstance();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.blay09.mods.waystones.cost;

import net.blay09.mods.waystones.xp.ExperienceLevelCost;
import net.minecraft.resources.ResourceLocation;

public class ExperienceLevelCostType implements CostType<ExperienceLevelCost> {

public static final ResourceLocation ID = new ResourceLocation("waystones", "experience_levels");

@Override
public ResourceLocation getId() {
return ID;
}

@Override
public ExperienceLevelCost createInstance() {
return new ExperienceLevelCost(0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.blay09.mods.waystones.cost;

import net.blay09.mods.waystones.xp.ExperiencePointsCost;
import net.minecraft.resources.ResourceLocation;

public class ExperiencePointsCostType implements CostType<ExperiencePointsCost> {

public static final ResourceLocation ID = new ResourceLocation("waystones", "experience_points");

@Override
public ResourceLocation getId() {
return ID;
}

@Override
public ExperiencePointsCost createInstance() {
return new ExperiencePointsCost(0);
}
}
Loading

0 comments on commit bf6198a

Please sign in to comment.