Feature modifiers and levels, limb overclocking, research improvements
This commit is contained in:
parent
38d34de609
commit
0365c09398
@ -1,6 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm;
|
||||
|
||||
import net.minecraft.client.gui.screens.MenuScreens;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
@ -16,6 +17,7 @@ import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.RegistryBuilder;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchType;
|
||||
import ru.dbotthepony.mc.otm.android.feature.AndroidLimbOverclocking;
|
||||
import ru.dbotthepony.mc.otm.block.*;
|
||||
import ru.dbotthepony.mc.otm.block.entity.*;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
|
||||
@ -102,8 +104,15 @@ public class Registry {
|
||||
|
||||
public static final ResourceLocation NUTRIENT_PASTE = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nutrient_paste");
|
||||
|
||||
// android features
|
||||
// android features and research
|
||||
public static final ResourceLocation AIR_BAGS = new ResourceLocation(OverdriveThatMatters.MOD_ID, "air_bags");
|
||||
public static final ResourceLocation LIMB_OVERCLOCKING = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking");
|
||||
public static final ResourceLocation LIMB_OVERCLOCKING_1 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_1");
|
||||
public static final ResourceLocation LIMB_OVERCLOCKING_2 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_2");
|
||||
public static final ResourceLocation LIMB_OVERCLOCKING_3 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_3");
|
||||
public static final ResourceLocation LIMB_OVERCLOCKING_4 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_4");
|
||||
|
||||
public static final ResourceLocation[] LIMB_OVERCLOCKING_LIST = new ResourceLocation[] { LIMB_OVERCLOCKING_1, LIMB_OVERCLOCKING_2, LIMB_OVERCLOCKING_3, LIMB_OVERCLOCKING_4 };
|
||||
}
|
||||
|
||||
public static class Blocks {
|
||||
@ -277,14 +286,17 @@ public class Registry {
|
||||
|
||||
public static class AndroidFeatures {
|
||||
public static final AndroidFeatureType<AndroidFeature> AIR_BAGS = new AndroidFeatureType<>(AndroidFeature::new);
|
||||
public static final AndroidFeatureType<AndroidLimbOverclocking> LIMB_OVERCLOCKING = new AndroidFeatureType<>(AndroidLimbOverclocking::new);
|
||||
|
||||
static {
|
||||
AIR_BAGS.setRegistryName(Names.AIR_BAGS);
|
||||
LIMB_OVERCLOCKING.setRegistryName(Names.LIMB_OVERCLOCKING);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void register(final RegistryEvent.Register<AndroidFeatureType<?>> event) {
|
||||
event.getRegistry().register(AIR_BAGS);
|
||||
event.getRegistry().register(LIMB_OVERCLOCKING);
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,13 +370,39 @@ public class Registry {
|
||||
.build()
|
||||
);
|
||||
|
||||
public static final AndroidResearchType<ru.dbotthepony.mc.otm.android.AndroidResearch>[] LIMB_OVERCLOCKING = new AndroidResearchType[4];
|
||||
|
||||
static {
|
||||
AIR_BAGS.setRegistryName(Names.AIR_BAGS);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
var builder = new ru.dbotthepony.mc.otm.android.AndroidResearch.Builder()
|
||||
.withDescription()
|
||||
.setExperienceCost(24 + i * 8)
|
||||
.withIconText(new TextComponent(String.valueOf(i + 1)))
|
||||
.withIcon(ICON_LIMB_OVERCLOCKING)
|
||||
.addFeatureResult(Names.LIMB_OVERCLOCKING, i);
|
||||
|
||||
if (i > 0) {
|
||||
builder.addPrerequisite(Names.LIMB_OVERCLOCKING_LIST[i - 1]);
|
||||
}
|
||||
|
||||
LIMB_OVERCLOCKING[i] = new AndroidResearchType<>(builder.build());
|
||||
}
|
||||
|
||||
LIMB_OVERCLOCKING[0].setRegistryName(Names.LIMB_OVERCLOCKING_1);
|
||||
LIMB_OVERCLOCKING[1].setRegistryName(Names.LIMB_OVERCLOCKING_2);
|
||||
LIMB_OVERCLOCKING[2].setRegistryName(Names.LIMB_OVERCLOCKING_3);
|
||||
LIMB_OVERCLOCKING[3].setRegistryName(Names.LIMB_OVERCLOCKING_4);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void register(final RegistryEvent.Register<AndroidResearchType<?>> event) {
|
||||
event.getRegistry().register(AIR_BAGS);
|
||||
event.getRegistry().register(LIMB_OVERCLOCKING[0]);
|
||||
event.getRegistry().register(LIMB_OVERCLOCKING[1]);
|
||||
event.getRegistry().register(LIMB_OVERCLOCKING[2]);
|
||||
event.getRegistry().register(LIMB_OVERCLOCKING[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,24 @@ public class AndroidFeature implements INBTSerializable<CompoundTag> {
|
||||
public final AndroidFeatureType<? extends AndroidFeature> type;
|
||||
public final IAndroidCapability capability;
|
||||
|
||||
protected int level = 0;
|
||||
|
||||
public AndroidFeature(AndroidFeatureType<?> type, IAndroidCapability capability) {
|
||||
this.type = type;
|
||||
this.capability = capability;
|
||||
}
|
||||
|
||||
public void setLevel(int level) {
|
||||
if (this.level != level) {
|
||||
this.level = level;
|
||||
applyModifiers();
|
||||
}
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj))
|
||||
@ -28,10 +41,6 @@ public class AndroidFeature implements INBTSerializable<CompoundTag> {
|
||||
// when player forgets everything
|
||||
}
|
||||
|
||||
public void attachFinish() {
|
||||
// override
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return type.hashCode();
|
||||
@ -45,8 +54,11 @@ public class AndroidFeature implements INBTSerializable<CompoundTag> {
|
||||
|
||||
}
|
||||
|
||||
public void serializeNBT(CompoundTag tag) {
|
||||
public void applyModifiers() {}
|
||||
public void removeModifiers() {}
|
||||
|
||||
public void serializeNBT(CompoundTag tag) {
|
||||
tag.putInt("level", level);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -58,6 +70,6 @@ public class AndroidFeature implements INBTSerializable<CompoundTag> {
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundTag tag) {
|
||||
|
||||
level = tag.getInt("level");
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +76,11 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Component getIconText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean research() {
|
||||
return research(false);
|
||||
}
|
||||
@ -102,12 +107,23 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
|
||||
|
||||
public static class Builder {
|
||||
record DeferredItemStack(ResourceLocation id, int amount) {}
|
||||
record DeferredFeature(ResourceLocation id, int level) {
|
||||
DeferredFeature(ResourceLocation id, int level) {
|
||||
this.id = id;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
DeferredFeature(ResourceLocation id) {
|
||||
this(id, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int experience = 0;
|
||||
public Component text;
|
||||
public boolean has_description = false;
|
||||
public final ArrayList<DeferredItemStack> items = new ArrayList<>();
|
||||
public final ArrayList<ResourceLocation> prerequisites = new ArrayList<>();
|
||||
public final ArrayList<ResourceLocation> feature_results = new ArrayList<>();
|
||||
public final ArrayList<DeferredFeature> feature_results = new ArrayList<>();
|
||||
public SkinElement icon;
|
||||
|
||||
public Builder addPrerequisite(ResourceLocation location) {
|
||||
@ -115,13 +131,28 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addPrerequisite(AndroidResearchType<?> location) {
|
||||
prerequisites.add(Objects.requireNonNull(location.getRegistryName()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addFeatureResult(ResourceLocation location) {
|
||||
feature_results.add(location);
|
||||
feature_results.add(new DeferredFeature(location));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addFeatureResult(AndroidFeatureType<?> location) {
|
||||
feature_results.add(Objects.requireNonNull(location.getRegistryName()));
|
||||
feature_results.add(new DeferredFeature(Objects.requireNonNull(location.getRegistryName())));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addFeatureResult(ResourceLocation location, int level) {
|
||||
feature_results.add(new DeferredFeature(location, level));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addFeatureResult(AndroidFeatureType<?> location, int level) {
|
||||
feature_results.add(new DeferredFeature(Objects.requireNonNull(location.getRegistryName()), level));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -150,9 +181,17 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withIconText(Component text) {
|
||||
this.text = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
private final ArrayList<ItemStack> resolved_stacks = new ArrayList<>();
|
||||
private final ArrayList<AndroidResearchType<?>> resolved_preq = new ArrayList<>();
|
||||
private final ArrayList<AndroidFeatureType<?>> resolved_features = new ArrayList<>();
|
||||
|
||||
record ResolvedFeature(AndroidFeatureType<?> type, int level) {}
|
||||
|
||||
private final ArrayList<ResolvedFeature> resolved_features = new ArrayList<>();
|
||||
|
||||
private boolean resolved = false;
|
||||
|
||||
@ -179,10 +218,10 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
|
||||
}
|
||||
|
||||
for (var entry : feature_results) {
|
||||
var get = Registry.ANDROID_FEATURES().getValue(entry);
|
||||
var get = Registry.ANDROID_FEATURES().getValue(entry.id);
|
||||
|
||||
if (get != null) {
|
||||
resolved_features.add(get);
|
||||
resolved_features.add(new ResolvedFeature(get, entry.level));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can not find android feature " + entry);
|
||||
}
|
||||
@ -201,6 +240,12 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Component getIconText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Component> getTooltip() {
|
||||
var list = new ArrayList<>(super.getTooltip());
|
||||
@ -256,12 +301,25 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
|
||||
@Override
|
||||
public void onResearched() {
|
||||
for (var feature : resolved_features) {
|
||||
capability.addFeature(feature);
|
||||
var get = capability.getFeature(feature.type);
|
||||
|
||||
if (get == null) {
|
||||
get = capability.addFeature(feature.type);
|
||||
get.setLevel(feature.level);
|
||||
} else if (get.getLevel() < feature.level) {
|
||||
get.setLevel(feature.level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAfford() {
|
||||
for (var preq : resolved_preq) {
|
||||
if (!capability.getResearch(preq).isResearched()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (capability.ply.experienceLevel < experience)
|
||||
return false;
|
||||
|
||||
|
@ -0,0 +1,43 @@
|
||||
package ru.dbotthepony.mc.otm.android.feature;
|
||||
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearch;
|
||||
import ru.dbotthepony.mc.otm.capability.IAndroidCapability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AndroidLimbOverclocking extends AndroidFeature {
|
||||
public final UUID MODIFIED_NAME = UUID.fromString("4a3fae46-e57b-4e20-857d-f5c2b2c8f2f2");
|
||||
|
||||
public AndroidLimbOverclocking(AndroidFeatureType<?> type, IAndroidCapability capability) {
|
||||
super(type, capability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyModifiers() {
|
||||
var speed = capability.getEntity().getAttribute(Attributes.MOVEMENT_SPEED);
|
||||
|
||||
OverdriveThatMatters.LOGGER.info("Get modifier {} {}", this, speed);
|
||||
|
||||
if (speed != null) {
|
||||
speed.removePermanentModifier(MODIFIED_NAME);
|
||||
speed.addPermanentModifier(new AttributeModifier(MODIFIED_NAME, type.getDisplayName().toString(), 0.08d * (level + 1), AttributeModifier.Operation.MULTIPLY_TOTAL));
|
||||
OverdriveThatMatters.LOGGER.info("Add modifier {} {}", this, capability.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeModifiers() {
|
||||
var speed = capability.getEntity().getAttribute(Attributes.MOVEMENT_SPEED);
|
||||
|
||||
if (speed != null) {
|
||||
speed.removePermanentModifier(MODIFIED_NAME);
|
||||
OverdriveThatMatters.LOGGER.info("Remove modifier {} {}", this, capability.getEntity());
|
||||
}
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ import net.minecraftforge.event.entity.living.LivingEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fmllegacy.network.PacketDistributor;
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
||||
import ru.dbotthepony.mc.otm.Registry;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
|
||||
@ -46,6 +47,8 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
|
||||
protected final Map<AndroidFeatureType<?>, AndroidFeature> features = new HashMap<>();
|
||||
protected final ArrayList<Object> network_queue = new ArrayList<>();
|
||||
|
||||
protected final ArrayList<Runnable> delayed_tick_server = new ArrayList<>();
|
||||
|
||||
protected boolean network_first = false;
|
||||
|
||||
protected boolean addFeature(@Nonnull AndroidFeature feature) {
|
||||
@ -54,6 +57,10 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
|
||||
|
||||
features.put(feature.type, feature);
|
||||
|
||||
if (!ent.level.isClientSide) {
|
||||
delayed_tick_server.add(feature::applyModifiers);
|
||||
}
|
||||
|
||||
if (ent instanceof ServerPlayer ply) {
|
||||
sendNetwork(new AndroidFeaturePacket(true, feature));
|
||||
}
|
||||
@ -62,18 +69,24 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFeature(@Nonnull AndroidFeatureType<?> feature) {
|
||||
if (features.containsKey(feature))
|
||||
return false;
|
||||
public AndroidFeature addFeature(@Nonnull AndroidFeatureType<?> feature) {
|
||||
var get = features.get(feature);
|
||||
|
||||
if (get != null)
|
||||
return get;
|
||||
|
||||
var factory = feature.factory(this);
|
||||
features.put(feature, factory);
|
||||
|
||||
if (!ent.level.isClientSide) {
|
||||
delayed_tick_server.add(factory::applyModifiers);
|
||||
}
|
||||
|
||||
if (ent instanceof ServerPlayer ply) {
|
||||
sendNetwork(new AndroidFeaturePacket(true, factory));
|
||||
}
|
||||
|
||||
return true;
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -81,6 +94,10 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
|
||||
var removed = features.remove(feature);
|
||||
|
||||
if (removed != null) {
|
||||
if (!ent.level.isClientSide) {
|
||||
delayed_tick_server.add(removed::removeModifiers);
|
||||
}
|
||||
|
||||
if (ent instanceof ServerPlayer ply) {
|
||||
sendNetwork(new AndroidFeaturePacket(false, removed));
|
||||
}
|
||||
@ -96,6 +113,17 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
|
||||
return features.containsKey(feature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFeatureLevel(@Nullable AndroidFeatureType<?> feature, int level) {
|
||||
var get = features.get(feature);
|
||||
|
||||
if (get == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return get.getLevel() >= level;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AndroidFeature getFeature(AndroidFeatureType<?> feature) {
|
||||
return features.get(feature);
|
||||
@ -199,7 +227,10 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
|
||||
feature.deserializeNBT(tag);
|
||||
|
||||
addFeature(feature);
|
||||
feature.attachFinish();
|
||||
|
||||
if (ent.level == null || !ent.level.isClientSide) {
|
||||
delayed_tick_server.add(feature::applyModifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -265,6 +296,8 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
|
||||
feature.tickClient();
|
||||
}
|
||||
}
|
||||
|
||||
delayed_tick_server.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -277,6 +310,12 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
|
||||
}
|
||||
}
|
||||
|
||||
for (var runnable : delayed_tick_server) {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
delayed_tick_server.clear();
|
||||
|
||||
tickNetwork();
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,10 @@ public interface IAndroidCapability extends IMatteryEnergyStorage, INBTSerializa
|
||||
void tickClient();
|
||||
LivingEntity getEntity();
|
||||
|
||||
boolean addFeature(@Nonnull AndroidFeatureType<?> feature);
|
||||
AndroidFeature addFeature(@Nonnull AndroidFeatureType<?> feature);
|
||||
boolean removeFeature(@Nonnull AndroidFeatureType<?> feature);
|
||||
boolean hasFeature(@Nullable AndroidFeatureType<?> feature);
|
||||
boolean hasFeatureLevel(@Nullable AndroidFeatureType<?> feature, int level);
|
||||
AndroidFeature getFeature(AndroidFeatureType<?> feature);
|
||||
|
||||
@Nonnull
|
||||
|
@ -50,6 +50,12 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> {
|
||||
} else {
|
||||
RenderHelper.drawRect(stack, 0, 0, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
var text = node.getIconText();
|
||||
|
||||
if (text != null) {
|
||||
font.drawShadow(stack, text, getWidth() - font.width(text), getHeight() - font.lineHeight, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -44,6 +44,21 @@
|
||||
"otm.android_station.research.missing_predecessors": "%s needs to be researched first",
|
||||
|
||||
"android_feature.overdrive_that_matters.air_bags": "Air bags",
|
||||
"android_feature.overdrive_that_matters.limb_overclocking_1": "Limb overclocking 1",
|
||||
"android_feature.overdrive_that_matters.limb_overclocking_2": "Limb overclocking 2",
|
||||
"android_feature.overdrive_that_matters.limb_overclocking_3": "Limb overclocking 3",
|
||||
"android_feature.overdrive_that_matters.limb_overclocking_4": "Limb overclocking 4",
|
||||
|
||||
"android_research.overdrive_that_matters.limb_overclocking_1": "Limb overclocking 1",
|
||||
"android_research.overdrive_that_matters.limb_overclocking_2": "Limb overclocking 2",
|
||||
"android_research.overdrive_that_matters.limb_overclocking_3": "Limb overclocking 3",
|
||||
"android_research.overdrive_that_matters.limb_overclocking_4": "Limb overclocking 4",
|
||||
|
||||
"android_research.overdrive_that_matters.limb_overclocking_1.description": "Boosts unit mobility by 8%% and attack speed by 4%%",
|
||||
"android_research.overdrive_that_matters.limb_overclocking_2.description": "Boosts unit mobility by 16%% and attack speed by 8%%",
|
||||
"android_research.overdrive_that_matters.limb_overclocking_3.description": "Boosts unit mobility by 24%% and attack speed by 12%%",
|
||||
"android_research.overdrive_that_matters.limb_overclocking_4.description": "Boosts unit mobility by 32%% and attack speed by 16%%",
|
||||
|
||||
"android_research.overdrive_that_matters.air_bags": "Air bags",
|
||||
"android_research.overdrive_that_matters.air_bags.description": "Allows unit to swim in water",
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user