Android feature research test

This commit is contained in:
DBotThePony 2021-08-19 20:44:43 +07:00
parent 74658e3a69
commit 68930672a4
Signed by: DBot
GPG Key ID: DCC23B5715498507
9 changed files with 292 additions and 6 deletions

View File

@ -18,6 +18,7 @@ import net.minecraftforge.registries.RegistryBuilder;
import ru.dbotthepony.mc.otm.block.*;
import ru.dbotthepony.mc.otm.block.entity.*;
import ru.dbotthepony.mc.otm.capability.android.AndroidAirBags;
import ru.dbotthepony.mc.otm.capability.android.AndroidAirBagsType;
import ru.dbotthepony.mc.otm.capability.android.AndroidFeatureType;
import ru.dbotthepony.mc.otm.item.ItemBattery;
import ru.dbotthepony.mc.otm.item.ItemMatterCapacitor;
@ -265,7 +266,7 @@ public class Registry {
}
public static class AndroidFeatures {
public static final AndroidFeatureType<AndroidAirBags> AIR_BAGS = new AndroidFeatureType<>(AndroidAirBags::new);
public static final AndroidAirBagsType AIR_BAGS = new AndroidAirBagsType();
static {
AIR_BAGS.setRegistryName(Names.AIR_BAGS);

View File

@ -0,0 +1,15 @@
package ru.dbotthepony.mc.otm.capability.android;
import javax.annotation.Nullable;
public class AndroidAirBagsType extends AndroidFeatureType<AndroidAirBags> {
public AndroidAirBagsType() {
super(AndroidAirBags::new);
}
@Nullable
@Override
public AndroidFeatureResearchNode getResearchNodeInner() {
return new AndroidFeatureResearchNode(this, new AndroidFeatureResearchCost(18));
}
}

View File

@ -199,7 +199,7 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
if (_tag instanceof CompoundTag tag) {
var get_feature = Registry.ANDROID_FEATURES().getValue(new ResourceLocation(tag.getString("id")));
if (get_feature != null) {
if (get_feature != null && get_feature.isApplicable(this)) {
var feature = get_feature.factory(this);
if (feature instanceof INBTSerializable serializable) {

View File

@ -0,0 +1,66 @@
package ru.dbotthepony.mc.otm.capability.android;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
public record AndroidFeatureResearchCost(int experience, ItemStack ...items) {
public boolean matches(Player ply) {
if (ply.experienceLevel < experience)
return false;
for (var stack : items) {
boolean hit = false;
if (stack.getTag() == null) {
for (var inv_stack : ply.getInventory().items) {
if (inv_stack.is(stack.getItem()) && inv_stack.getCount() >= stack.getCount()) {
hit = true;
break;
}
}
} else {
for (var inv_stack : ply.getInventory().items) {
if (inv_stack.is(stack.getItem()) && inv_stack.getCount() >= stack.getCount() && inv_stack.getTag() != null && inv_stack.getTag().equals(stack.getTag())) {
hit = true;
break;
}
}
}
if (!hit)
return false;
}
return true;
}
public boolean research(Player ply) {
if (!matches(ply))
return false;
if (experience > 0)
ply.giveExperienceLevels(-experience);
for (var stack : items) {
if (stack.getTag() == null) {
for (var inv_stack : ply.getInventory().items) {
if (inv_stack.is(stack.getItem()) && inv_stack.getCount() >= stack.getCount()) {
inv_stack.shrink(stack.getCount());
break;
}
}
} else {
for (var inv_stack : ply.getInventory().items) {
if (inv_stack.is(stack.getItem()) && inv_stack.getCount() >= stack.getCount() && inv_stack.getTag() != null && inv_stack.getTag().equals(stack.getTag())) {
inv_stack.shrink(stack.getCount());
break;
}
}
}
}
ply.getInventory().setChanged();
return true;
}
}

View File

@ -0,0 +1,75 @@
package ru.dbotthepony.mc.otm.capability.android;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Player;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
import ru.dbotthepony.mc.otm.network.android.AndroidResearchRequestPacket;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class AndroidFeatureResearchNode {
public final AndroidFeatureType<?> type;
public final AndroidFeatureResearchCost cost;
public final Set<AndroidFeatureType<?>> predecessors = new HashSet<>();
protected final Component name;
public AndroidFeatureResearchNode(AndroidFeatureType<?> type, AndroidFeatureResearchCost cost) {
this.type = type;
this.cost = cost;
name = new TranslatableComponent("android_feature." + type.getRegistryName().getNamespace() + "." + type.getRegistryName().getPath());
}
public AndroidFeatureResearchNode addPredecessor(AndroidFeatureType<?> value) {
predecessors.add(value);
return this;
}
public boolean canResearch(Player ply, AndroidCapabilityPlayer cap) {
for (var prec : predecessors) {
if (!cap.hasFeature(prec))
return false;
}
return cost.matches(ply);
}
public void research(Player ply, AndroidCapabilityPlayer cap) {
if (cap.hasFeature(type))
return;
if (!canResearch(ply, cap))
return;
cost.research(ply);
cap.addFeature(type);
}
public void researchClient() {
var ply = Minecraft.getInstance().player;
ply.getCapability(MatteryCapability.ANDROID).ifPresent(cap -> {
if (cap.hasFeature(type))
return;
if (!canResearch(ply, (AndroidCapabilityPlayer) cap))
return;
MatteryNetworking.CHANNEL.sendToServer(new AndroidResearchRequestPacket(type));
});
}
public Component getName() {
return name;
}
public List<Component> getTooltip() {
return List.of(getName());
}
}

View File

@ -3,6 +3,8 @@ package ru.dbotthepony.mc.otm.capability.android;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.registries.*;
import javax.annotation.Nullable;
public class AndroidFeatureType<T extends AndroidFeature> extends ForgeRegistryEntry<AndroidFeatureType<?>> {
public interface AndroidFeatureFactory<T extends AndroidFeature> {
T factory(AndroidFeatureType<T> entry, IAndroidCapability capability);
@ -21,4 +23,23 @@ public class AndroidFeatureType<T extends AndroidFeature> extends ForgeRegistryE
public boolean isApplicable(IAndroidCapability capability) {
return true;
}
public boolean isResearchable() {
return false;
}
@Nullable
protected AndroidFeatureResearchNode getResearchNodeInner() {
return null;
}
private AndroidFeatureResearchNode cache;
@Nullable
public AndroidFeatureResearchNode getResearchNode() {
if (cache != null)
return cache;
return cache = getResearchNodeInner();
}
}

View File

@ -5,10 +5,7 @@ import net.minecraftforge.fmllegacy.network.NetworkDirection;
import net.minecraftforge.fmllegacy.network.NetworkRegistry;
import net.minecraftforge.fmllegacy.network.simple.SimpleChannel;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.network.android.AndroidBatteryPacket;
import ru.dbotthepony.mc.otm.network.android.AndroidEnergyPacket;
import ru.dbotthepony.mc.otm.network.android.AndroidFeaturePacket;
import ru.dbotthepony.mc.otm.network.android.AndroidStatusPacket;
import ru.dbotthepony.mc.otm.network.android.*;
import java.util.Optional;
@ -105,5 +102,14 @@ public class MatteryNetworking {
MatterRegistryPacket::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
AndroidResearchRequestPacket.class,
AndroidResearchRequestPacket::write,
AndroidResearchRequestPacket::read,
AndroidResearchRequestPacket::play,
Optional.of(NetworkDirection.PLAY_TO_SERVER)
);
}
}

View File

@ -0,0 +1,52 @@
package ru.dbotthepony.mc.otm.network.android;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer;
import ru.dbotthepony.mc.otm.capability.android.AndroidFeature;
import ru.dbotthepony.mc.otm.capability.android.AndroidFeatureType;
import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability;
import java.util.Objects;
import java.util.function.Supplier;
public record AndroidResearchRequestPacket(AndroidFeatureType<?> feature) {
public AndroidResearchRequestPacket(AndroidFeatureType<?> feature) {
this.feature = feature;
}
public AndroidResearchRequestPacket(AndroidFeature feature) {
this(feature.type);
}
public void write(FriendlyByteBuf buffer) {
buffer.writeInt(Registry.ANDROID_FEATURES().getID(feature));
}
public void play(Supplier<NetworkEvent.Context> context) {
context.get().setPacketHandled(true);
context.get().enqueueWork(() -> context.get().getSender().getCapability(MatteryCapability.ANDROID).ifPresent(cap -> this.playServer((AndroidCapabilityPlayer) cap, (ServerPlayer) context.get().getSender())));
}
public void playServer(AndroidCapabilityPlayer cap, ServerPlayer ply) {
if (cap.hasFeature(feature))
return;
var node = feature.getResearchNode();
if (node == null)
return;
node.research(ply, cap);
}
public static AndroidResearchRequestPacket read(FriendlyByteBuf buffer) {
return new AndroidResearchRequestPacket(Objects.requireNonNull(Registry.ANDROID_FEATURES().getValue(buffer.readInt())));
}
}

View File

@ -1,11 +1,17 @@
package ru.dbotthepony.mc.otm.screen;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.capability.android.AndroidFeatureResearchNode;
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu;
import java.util.HashSet;
import java.util.Set;
public class AndroidStationScreen extends PoweredMachineScreen<AndroidStationMenu> {
private static final ResourceLocation CONTAINER_BACKGROUND = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/android_station.png");
@ -14,7 +20,51 @@ public class AndroidStationScreen extends PoweredMachineScreen<AndroidStationMen
return CONTAINER_BACKGROUND;
}
private final Set<AndroidFeatureResearchNode> nodes = new HashSet<>();
public AndroidStationScreen(AndroidStationMenu p_97741_, Inventory p_97742_, Component p_97743_) {
super(p_97741_, p_97742_, p_97743_);
for (var feature : Registry.ANDROID_FEATURES().getValues()) {
var node = feature.getResearchNode();
if (node != null) {
nodes.add(node);
}
}
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int p_97750_) {
int x = leftPos + 40;
int y = topPos + 10;
for (var node : nodes) {
if (mouseX >= x && mouseX <= x + 16 && mouseY >= y && mouseY <= y + 16) {
node.researchClient();
return true;
}
}
return super.mouseClicked(mouseX, mouseY, p_97750_);
}
@Override
protected void renderTooltip(PoseStack pose, int mouseX, int mouseY) {
super.renderTooltip(pose, mouseX, mouseY);
int x = leftPos + 40;
int y = topPos + 10;
for (var node : nodes) {
if (mouseX >= x && mouseX <= x + 16 && mouseY >= y && mouseY <= y + 16) {
renderComponentTooltip(pose, node.getTooltip(), mouseX, mouseY);
}
}
}
@Override
protected void renderBg(PoseStack pose, float p_97788_, int mouseX, int mouseY) {
super.renderBg(pose, p_97788_, mouseX, mouseY);
}
}