Skip to content

Instantly share code, notes, and snippets.

@Lanse505
Created August 3, 2022 11:36
Show Gist options
  • Save Lanse505/b0aa98477fadaf3ba4578e370907fdf3 to your computer and use it in GitHub Desktop.
Save Lanse505/b0aa98477fadaf3ba4578e370907fdf3 to your computer and use it in GitHub Desktop.
package matteroverdrive.core.component.container;
import com.hrznstudio.titanium.api.IFactory;
import com.hrznstudio.titanium.container.BasicAddonContainer;
import com.hrznstudio.titanium.container.addon.IContainerAddonProvider;
import com.hrznstudio.titanium.network.locator.LocatorInstance;
import matteroverdrive.core.component.util.property.IPropertyManaged;
import matteroverdrive.core.component.util.property.PropertyManager;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.inventory.ContainerListener;
import net.minecraft.world.inventory.MenuType;
import net.minecraftforge.registries.ObjectHolder;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class MatterOverdriveAddonContainer extends BasicAddonContainer implements IPropertyManaged {
@ObjectHolder(registryName = "minecraft:menu", value = "matteroverdrive:addon_container")
public static MenuType<MatterOverdriveAddonContainer> TYPE;
private final PropertyManager propertyManager;
public MatterOverdriveAddonContainer(Object provider, LocatorInstance locatorInstance, ContainerLevelAccess worldPosCallable, Inventory playerInventory, int containerId) {
super(provider, locatorInstance, TYPE, worldPosCallable, playerInventory, containerId);
this.propertyManager = new PropertyManager((short) containerId);
if (this.getProvider() instanceof IContainerAddonProvider addonProvider) {
addonProvider.getContainerAddons()
.stream()
.map(IFactory::create)
.forEach(addon -> {
if (addon instanceof PropertyHolderAddon propHolder) {
propHolder.getProperties().forEach(propertyManager::addTrackedProperty);
}
});
}
}
@Override
public void addSlotListener(@NotNull ContainerListener listener) {
super.addSlotListener(listener);
this.propertyManager.sendChanges(Collections.singletonList(listener), true);
}
@Override
public void broadcastChanges() {
super.broadcastChanges();
this.getPropertyManager().sendChanges(this.containerListeners, false);
}
@Override
public PropertyManager getPropertyManager() {
return this.propertyManager;
}
}
package matteroverdrive.core.component.addons;
import com.hrznstudio.titanium.api.IFactory;
import com.hrznstudio.titanium.api.client.IScreenAddon;
import com.hrznstudio.titanium.api.client.IScreenAddonProvider;
import com.hrznstudio.titanium.component.IComponentHarness;
import com.hrznstudio.titanium.container.addon.IContainerAddon;
import com.hrznstudio.titanium.container.addon.IContainerAddonProvider;
import com.hrznstudio.titanium.container.addon.IntReferenceHolderAddon;
import com.hrznstudio.titanium.container.referenceholder.FunctionReferenceHolder;
import matteroverdrive.core.capability.types.matter.CapabilityMatterStorage;
import matteroverdrive.core.capability.types.matter.ICapabilityMatterStorage;
import matteroverdrive.core.component.addons.matter.MatterContainerAddon;
import matteroverdrive.core.component.addons.matter.MatterScreenAddon;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.common.util.INBTSerializable;
import org.apache.commons.compress.utils.Lists;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class MatterComponent<T extends IComponentHarness>
extends CapabilityMatterStorage
implements IScreenAddonProvider, IContainerAddonProvider, INBTSerializable<CompoundTag> {
private final int posX;
private final int posY;
private String name;
private T componentHarness;
private Action action;
public MatterComponent(double maxStorage, int posX, int posY, String name, Action defaultAction) {
super(maxStorage, defaultAction.canFill(), defaultAction.canDrain());
this.posX = posX;
this.posY = posY;
this.name = name;
this.action = defaultAction;
}
public MatterComponent<T> setComponentHarness(T componentHarness) {
this.componentHarness = componentHarness;
return this;
}
public T getComponentHarness() {
return componentHarness;
}
@Override
public double receiveMatter(double maxReceive, boolean simulate) {
return super.receiveMatter(maxReceive, simulate);
}
@Override
public double extractMatter(double maxExtract, boolean simulate) {
return super.extractMatter(maxExtract, simulate);
}
@Override
public boolean canExtract() {
return this.action.canDrain();
}
@Override
public boolean canReceive() {
return this.action.canFill();
}
@NotNull
@Override
public List<IFactory<? extends IScreenAddon>> getScreenAddons() {
List<IFactory<? extends IScreenAddon>> addons = new ArrayList<>();
addons.add(() -> new MatterScreenAddon(posX, posY, this));
return addons;
}
@NotNull
@Override
public List<IFactory<? extends IContainerAddon>> getContainerAddons() {
List<IFactory<? extends IContainerAddon>> addons = new ArrayList<>();
addons.add(() -> new MatterContainerAddon(getComponentHarness()));
return addons;
}
public String getName() {
return name;
}
public enum Action {
FILL(true, false),
DRAIN(false, true),
BOTH(true, true),
NONE(false, false);
private final boolean fill;
private final boolean drain;
Action(boolean fill, boolean drain) {
this.fill = fill;
this.drain = drain;
}
public boolean canFill() {
return this.fill;
}
public boolean canDrain() {
return this.drain;
}
}
}
package matteroverdrive.core.component.addons.matter;
import com.hrznstudio.titanium.Titanium;
import com.hrznstudio.titanium.api.client.IAsset;
import com.hrznstudio.titanium.client.screen.addon.BasicScreenAddon;
import com.hrznstudio.titanium.client.screen.asset.IAssetProvider;
import com.hrznstudio.titanium.network.locator.ILocatable;
import com.hrznstudio.titanium.network.messages.ButtonClickNetworkMessage;
import com.mojang.blaze3d.vertex.PoseStack;
import matteroverdrive.common.item.tools.ItemMatterContainer;
import matteroverdrive.core.capability.MatterOverdriveCapabilities;
import matteroverdrive.core.capability.types.matter.CapabilityMatterStorage;
import matteroverdrive.core.capability.types.matter.ICapabilityMatterStorage;
import matteroverdrive.core.component.addons.MatterComponent;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class MatterScreenAddon extends BasicScreenAddon {
private ICapabilityMatterStorage storage;
private IAsset asset;
public MatterScreenAddon(int posX, int posY, ICapabilityMatterStorage storage) {
super(posX, posY);
this.storage = storage;
}
@Override
public void drawBackgroundLayer(PoseStack stack, Screen screen, IAssetProvider provider, int guiX, int guiY, int mouseX, int mouseY, float partialTicks) {
}
@Override
public void drawForegroundLayer(PoseStack stack, Screen screen, IAssetProvider provider, int guiX, int guiY, int mouseX, int mouseY, float partialTicks) {}
@Override
public List<Component> getTooltipLines() {
List<Component> tooltips = new ArrayList<>();
tooltips.add(Component.empty()
// Default Gold Color
.withStyle(ChatFormatting.GOLD)
// Default Matter Text
.append(Component.translatable("tooltip.matteroverdrive.matterstorage.matter"))
.append(storage.getMatterStored() > 0 ?
// If it has stored matter add the stored tooltip
Component.translatable("tooltip.matteroverdrive.matterstorage.stored")
.withStyle(ChatFormatting.WHITE) :
// If it doesn't have stored matter then add the empty tooltip
Component.translatable("tooltip.matteroverdrive.matterstorage.empty")
.withStyle(ChatFormatting.WHITE)
)
);
// Add the amount tooltip
tooltips.add(Component.translatable("tooltip.matteroverdrive.matterstorage.amount")
// Default Gold Color
.withStyle(ChatFormatting.GOLD)
// Add Decimal-Formatted information with ROOT locale
.append(Component.literal(
ChatFormatting.WHITE +
DecimalFormat.getInstance(Locale.ROOT).format(storage.getMatterStored()) +
ChatFormatting.GOLD +
"/" +
ChatFormatting.WHITE +
DecimalFormat.getInstance(Locale.ROOT).format(storage.getMaxMatterStored()) +
ChatFormatting.DARK_AQUA +
"mb"
)
)
);
if (Minecraft.getInstance().player != null) {
ItemStack carried = Minecraft.getInstance().player.containerMenu.getCarried();
// If the item held on the cursor is a capability holder of the MatterStorage cap.
if (!carried.isEmpty() && carried.getCapability(MatterOverdriveCapabilities.MATTER_STORAGE).isPresent()) {
// Then get the capability
carried.getCapability(MatterOverdriveCapabilities.MATTER_STORAGE).ifPresent(storageCap -> {
// Check that it's also an ItemMatterContainer
boolean isStorage = carried.getItem() instanceof ItemMatterContainer;
// If it's an ItemMatterContainer then get the maxMatterStored, otherwise default to Double.MAX_VALUE
double amount = isStorage ? storageCap.getMaxMatterStored() : Double.MAX_VALUE;
// Simulate both ways for fill and drain to check if the carried item can fill or drain into the storage.
boolean canFillFromItem = storage.receiveMatter(storageCap.extractMatter(amount, true), true) == amount;
boolean canDrainFromItem = storageCap.receiveMatter(storage.extractMatter(amount, true), true) == amount;
// Add appropriate tooltips where needed.
if (canFillFromItem)
tooltips.add(Component.translatable("tooltip.matteroverdrive.matterstorage.can_fill_from_item")
.withStyle(ChatFormatting.BLUE));
if (canDrainFromItem)
tooltips.add(Component.translatable("tooltip.matteroverdrive.matterstorage.can_drain_from_item")
.withStyle(ChatFormatting.GOLD));
if (canFillFromItem)
tooltips.add(Component.translatable("tooltip.matteroverdrive.matterstorage.action_fill")
.withStyle(ChatFormatting.DARK_GRAY));
if (canDrainFromItem)
tooltips.add(Component.translatable("tooltip.matteroverdrive.matterstorage.action_drain")
.withStyle(ChatFormatting.DARK_GRAY));
if (!canFillFromItem && !canDrainFromItem)
tooltips.add(Component.translatable("tooltip.matteroverdrive.matterstorage.no_action"));
});
} else {
// If the item doesn't have the MatterStorage Capability then just state that the item has no storage.
tooltips.add(Component.translatable("tooltips.matteroverdrive.matterstorage.no_storage"));
}
}
// Finally return the tooltip list.
return tooltips;
}
@Override
public int getXSize() {
return asset != null ? asset.getArea().width : 0;
}
@Override
public int getYSize() {
return asset != null ? asset.getArea().height : 0;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (!Minecraft.getInstance().player.containerMenu.getCarried().isEmpty() &&
Minecraft.getInstance().player.containerMenu.getCarried().getCapability(MatterOverdriveCapabilities.MATTER_STORAGE).isPresent()) {
ItemStack carried = Minecraft.getInstance().player.containerMenu.getCarried();
Screen screen = Minecraft.getInstance().screen;
if (screen instanceof AbstractContainerScreen<?> abstractScreen &&
abstractScreen.getMenu() instanceof ILocatable locatable) {
if (!isMouseOver(mouseX - abstractScreen.getGuiLeft(), mouseY - abstractScreen.getGuiTop()))
return false;
Minecraft.getInstance().getSoundManager().play(
new SimpleSoundInstance(
SoundEvents.UI_BUTTON_CLICK, SoundSource.PLAYERS,
1f, 1f,
RandomSource.create(),
Minecraft.getInstance().player.blockPosition()
));
CompoundTag tag = new CompoundTag();
if (storage instanceof MatterComponent<?> component) {
tag.putString("Name", component.getName());
} else tag.putBoolean("Invalid", true);
carried.getCapability(MatterOverdriveCapabilities.MATTER_STORAGE).ifPresent(storageCap -> {
boolean isStorage = carried.getItem() instanceof ItemMatterContainer;
double amount = isStorage ? storageCap.getMaxMatterStored() : Double.MAX_VALUE;
boolean canFillFromItem = storage.receiveMatter(storageCap.extractMatter(amount, true), true) == amount;
boolean canDrainFromItem = storageCap.receiveMatter(storage.extractMatter(amount, true), true) == amount;
if (canFillFromItem && button == 0) tag.putBoolean("Fill", true);
if (canDrainFromItem && button == 1) tag.putBoolean("Fill", false);
});
Titanium.NETWORK.get().sendToServer(new ButtonClickNetworkMessage(locatable.getLocatorInstance(), -3, tag));
return true;
}
}
return false;
}
}
package matteroverdrive.core.component.addons.matter;
import com.hrznstudio.titanium.block.tile.BasicTile;
import com.hrznstudio.titanium.component.IComponentHarness;
import matteroverdrive.core.capability.MatterOverdriveCapabilities;
import matteroverdrive.core.capability.types.matter.ICapabilityMatterStorage;
import matteroverdrive.core.component.container.PropertyHolderAddon;
import matteroverdrive.core.component.util.property.Property;
import matteroverdrive.core.component.util.property.PropertyTypes;
public class MatterContainerAddon extends PropertyHolderAddon {
private final Property<Double> matter;
public MatterContainerAddon(IComponentHarness harness) {
this.matter = addProperty(PropertyTypes.DOUBLE, () -> this.getStoredMatter(harness), (amount) -> this.setStoredMatter(harness, amount));
}
public Property<Double> getMatter() {
return matter;
}
private double getStoredMatter(IComponentHarness harness) {
if (harness instanceof BasicTile<?> tile && tile.getCapability(MatterOverdriveCapabilities.MATTER_STORAGE).isPresent()) {
this.matter.set(tile.getCapability(MatterOverdriveCapabilities.MATTER_STORAGE).map(ICapabilityMatterStorage::getMatterStored).orElse(0D));
return this.matter.get();
}
return 0;
}
private void setStoredMatter(IComponentHarness harness, double amount) {
if (harness instanceof BasicTile<?> tile && tile.getCapability(MatterOverdriveCapabilities.MATTER_STORAGE).isPresent()) {
this.matter.set(amount);
tile.getCapability(MatterOverdriveCapabilities.MATTER_STORAGE).ifPresent(storage -> storage.setMatterStored(amount));
}
}
}
package matteroverdrive.core.component.container;
import com.hrznstudio.titanium.container.addon.IContainerAddon;
import matteroverdrive.core.component.util.property.Property;
import matteroverdrive.core.component.util.property.PropertyType;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class PropertyHolderAddon implements IContainerAddon, IPropertyHolder {
private final List<Property<?>> properties;
public PropertyHolderAddon() {
this.properties = new ArrayList<>();
}
@Override
public List<Property<?>> getProperties() {
return properties;
}
public <T> Property<T> addProperty(PropertyType<T> property, Supplier<T> getter, Consumer<T> setter) {
Property<T> prop = property.create(getter, setter);
this.properties.add(prop);
return prop;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment