Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import java.util.function.Supplier;

import com.simibubi.create.Create;
import com.simibubi.create.content.trains.schedule.condition.DeliverPackageCondition;
import com.simibubi.create.content.trains.schedule.condition.FluidThresholdCondition;
import com.simibubi.create.content.trains.schedule.condition.IdleCargoCondition;
import com.simibubi.create.content.trains.schedule.condition.ItemThresholdCondition;
import com.simibubi.create.content.trains.schedule.condition.RetrievePackageCondition;
import com.simibubi.create.content.trains.schedule.condition.PlayerPassengerCondition;
import com.simibubi.create.content.trains.schedule.condition.RedstoneLinkCondition;
import com.simibubi.create.content.trains.schedule.condition.ScheduleWaitCondition;
Expand Down Expand Up @@ -63,6 +65,8 @@ public class Schedule {
registerCondition("idle", IdleCargoCondition::new);
registerCondition("unloaded", StationUnloadedCondition::new);
registerCondition("powered", StationPoweredCondition::new);
registerCondition("retrieve_package", RetrievePackageCondition::new);
registerCondition("deliver_package", DeliverPackageCondition::new);
}

private static void registerInstruction(String name, Supplier<? extends ScheduleInstruction> factory) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.simibubi.create.content.trains.schedule.condition;

import com.google.common.collect.ImmutableList;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.box.PackageItem;
import com.simibubi.create.content.logistics.box.PackageStyles;
import com.simibubi.create.content.logistics.packagePort.postbox.PostboxBlockEntity;
import com.simibubi.create.content.trains.entity.Carriage;
import com.simibubi.create.content.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.content.trains.entity.Train;
import com.simibubi.create.content.trains.station.GlobalStation.GlobalPackagePort;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.CreateLang;

import net.createmod.catnip.data.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.IItemHandlerModifiable;
import net.neoforged.neoforge.items.ItemHandlerHelper;

import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map.Entry;

public class DeliverPackageCondition extends ScheduleWaitCondition {

public DeliverPackageCondition() {
}

@Override
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
return true;
}

@Override
public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) {
return CreateLang.translateDirect("schedule.condition.deliver_package.status");
}

@Override
public Pair<ItemStack, Component> getSummary() {
return Pair.of(PackageStyles.getDefaultBox(), CreateLang.translateDirect("schedule.condition.deliver_package.summary"));
}

@Override
public List<Component> getTitleAs(String type) {
return ImmutableList.of(
Component.translatable(getId().getNamespace() + ".schedule." + type + "." + getId().getPath()));
}

@Override
public ResourceLocation getId() {
return Create.asResource("deliver_package");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.simibubi.create.content.trains.schedule.condition;

import com.google.common.collect.ImmutableList;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.box.PackageItem;
import com.simibubi.create.content.logistics.box.PackageStyles;
import com.simibubi.create.content.logistics.packagePort.postbox.PostboxBlockEntity;
import com.simibubi.create.content.trains.entity.Carriage;
import com.simibubi.create.content.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.content.trains.entity.Train;

import com.simibubi.create.content.trains.station.GlobalStation.GlobalPackagePort;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.CreateLang;

import net.createmod.catnip.data.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;

import net.neoforged.neoforge.items.IItemHandlerModifiable;

import net.neoforged.neoforge.items.ItemHandlerHelper;

import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map.Entry;

public class RetrievePackageCondition extends ScheduleWaitCondition {

public RetrievePackageCondition() {
data.putString("Filter", "");
}

@Override
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
return true;
}

@Override
public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) {
return CreateLang.translateDirect("schedule.condition.retrieve_package.status", getFilter());
}

@Override
public Pair<ItemStack, Component> getSummary() {
return Pair.of(PackageStyles.getDefaultBox(), CreateLang.translateDirect("schedule.condition.retrieve_package.summary"));
}

@Override
public List<Component> getTitleAs(String type) {
return ImmutableList.of(
Component.translatable(getId().getNamespace() + ".schedule." + type + "." + getId().getPath()),
CreateLang.translateDirect("schedule.condition.retrieve_package.addressed", getFilter())
.withStyle(ChatFormatting.DARK_AQUA));
}

@Override
public ResourceLocation getId() {
return Create.asResource("retrieve_package");
}

@OnlyIn(Dist.CLIENT)
protected void modifyEditBox(EditBox box) {
box.setFilter(s -> StringUtils.countMatches(s, '*') <= 3);
}

@Override
@OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
builder.addTextInput(0, 121, (e, t) -> modifyEditBox(e), "Filter");
}

public String getFilter() {
return textData("Filter");
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.simibubi.create.content.trains.station;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

Expand All @@ -15,6 +17,13 @@
import com.simibubi.create.content.trains.entity.Train;
import com.simibubi.create.content.trains.graph.DimensionPalette;
import com.simibubi.create.content.trains.graph.TrackNode;
import com.simibubi.create.content.trains.schedule.ScheduleEntry;
import com.simibubi.create.content.trains.schedule.condition.DeliverPackageCondition;
import com.simibubi.create.content.trains.schedule.condition.RetrievePackageCondition;
import com.simibubi.create.content.trains.schedule.condition.ScheduleWaitCondition;
import com.simibubi.create.content.trains.schedule.destination.DeliverPackagesInstruction;
import com.simibubi.create.content.trains.schedule.destination.DestinationInstruction;
import com.simibubi.create.content.trains.schedule.destination.FetchPackagesInstruction;
import com.simibubi.create.content.trains.signal.SingleBlockEntityEdgePoint;

import net.createmod.catnip.nbt.NBTHelper;
Expand Down Expand Up @@ -170,12 +179,170 @@ public static class GlobalPackagePort {
public boolean primed = false;
}

private List<String> getRetrievePackageFilters() {
Train train = getNearestTrain();
if (train == null || train.runtime.schedule == null || train.runtime.schedule.entries.isEmpty()) new ArrayList<String>();
ScheduleEntry entry = train.runtime.schedule.entries.get(train.runtime.currentEntry);
List<String> filters = new ArrayList<>();

if (entry.instruction instanceof FetchPackagesInstruction fetchPackagesInstruction) {
filters.add(fetchPackagesInstruction.getFilter());
return filters;
}

for (var i = 0; i < entry.conditions.size(); i++) {
List<ScheduleWaitCondition> entryConditions = entry.conditions.get(i);
for (var entryCondition : entryConditions) {
if (entryCondition instanceof RetrievePackageCondition retrieveCondition) {
filters.add(retrieveCondition.getFilter());
}
}
}
return filters;
}

private boolean hasDeliverPackageCondition() {
Train train = getNearestTrain();
if (train == null || train.runtime.schedule == null || train.runtime.schedule.entries.isEmpty()) return false;
ScheduleEntry entry = train.runtime.schedule.entries.get(train.runtime.currentEntry);
for (var i = 0; i < entry.conditions.size(); i++) {
List<ScheduleWaitCondition> entryConditions = entry.conditions.get(i);
for (var entryCondition : entryConditions) {
if (entryCondition instanceof DeliverPackageCondition) {
return true;
}
}
}
return false;
}

private boolean isDeliverPackageInstruction() {
Train train = getNearestTrain();
if (train == null || train.runtime.schedule == null || train.runtime.schedule.entries.isEmpty()) return false;
ScheduleEntry entry = train.runtime.schedule.entries.get(train.runtime.currentEntry);
if (entry.instruction instanceof DeliverPackagesInstruction) {
return true;
}
return false;
}

private boolean shouldDeliverPackages() {
return hasDeliverPackageCondition() || isDeliverPackageInstruction();
}

public void runMailTransferScheduled() {
Train train = getPresentTrain();
if (train == null || connectedPorts.isEmpty())
return;
Level level = null;

if (train.runtime.schedule == null) return;


var shouldDeliverPackages = shouldDeliverPackages();
var retrievePackageFilters = getRetrievePackageFilters();
for (Carriage carriage : train.carriages) {
if (level == null) {
CarriageContraptionEntity entity = carriage.anyAvailableEntity();
if (entity != null && entity.level() instanceof ServerLevel sl)
level = sl.getServer()
.getLevel(getBlockEntityDimension());
}

IItemHandlerModifiable carriageInventory = carriage.storage.getAllItems();
if (carriageInventory == null)
continue;

// Import from station
if (retrievePackageFilters != null && !retrievePackageFilters.isEmpty()) {
for (Entry<BlockPos, GlobalPackagePort> entry : connectedPorts.entrySet()) {
GlobalPackagePort port = entry.getValue();
BlockPos pos = entry.getKey();
PostboxBlockEntity box = null;

IItemHandlerModifiable postboxInventory = port.offlineBuffer;
if (level != null && level.isLoaded(pos)
&& level.getBlockEntity(pos) instanceof PostboxBlockEntity ppbe) {
postboxInventory = ppbe.inventory;
box = ppbe;
}

for (int slot = 0; slot < postboxInventory.getSlots(); slot++) {
ItemStack stack = postboxInventory.getStackInSlot(slot);
if (!PackageItem.isPackage(stack))
continue;
if (PackageItem.matchAddress(stack, port.address))
continue;

// Only import if we have matching conditions
for (var filter : retrievePackageFilters) {
if (PackageItem.matchAddress(stack, filter)) {
ItemStack result = ItemHandlerHelper.insertItemStacked(carriageInventory, stack, false);
if (!result.isEmpty())
break;

postboxInventory.setStackInSlot(slot, ItemStack.EMPTY);
Create.RAILWAYS.markTracksDirty();
if (box != null)
box.spawnParticles();

break;
}
}
}
}
}

// Only export if we have the condition to
if (shouldDeliverPackages) {
// Export to station
for (int slot = 0; slot < carriageInventory.getSlots(); slot++) {
ItemStack stack = carriageInventory.getStackInSlot(slot);
if (!PackageItem.isPackage(stack))
continue;

for (Entry<BlockPos, GlobalPackagePort> entry : connectedPorts.entrySet()) {
GlobalPackagePort port = entry.getValue();
BlockPos pos = entry.getKey();
PostboxBlockEntity box = null;

if (!PackageItem.matchAddress(stack, port.address))
continue;

IItemHandler postboxInventory = port.offlineBuffer;
if (level != null && level.isLoaded(pos)
&& level.getBlockEntity(pos) instanceof PostboxBlockEntity ppbe) {
postboxInventory = ppbe.inventory;
box = ppbe;
}

ItemStack result = ItemHandlerHelper.insertItemStacked(postboxInventory, stack, false);
if (!result.isEmpty())
continue;

Create.RAILWAYS.markTracksDirty();
carriageInventory.setStackInSlot(slot, ItemStack.EMPTY);
if (box != null)
box.spawnParticles();

break;
}
}
}
}
}

public void runMailTransfer() {
Train train = getPresentTrain();
if (train == null || connectedPorts.isEmpty())
return;
Level level = null;

if (train.runtime.schedule != null) {
runMailTransferScheduled();
return;
}

for (Carriage carriage : train.carriages) {
if (level == null) {
CarriageContraptionEntity entity = carriage.anyAvailableEntity();
Expand Down
10 changes: 9 additions & 1 deletion src/main/resources/assets/create/lang/default/interface.json
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@
"create.schedule.instruction.address_filter_edit_box_2": "Train may navigate anywhere to collect it",
"create.schedule.instruction.address_filter_edit_box_3": "Add another instruction to make it return",

"create.schedule.condition_type": "Continue if/after:",
"create.schedule.condition_type": "Continue if/after:",
"create.schedule.condition.editor": "Condition Editor",

"create.schedule.condition.delay": "Scheduled Delay",
Expand Down Expand Up @@ -856,6 +856,14 @@
"create.schedule.condition.redstone_link.frequency_state": "Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "Frequency not powered:",
"create.schedule.condition.retrieve_package": "Retrieve Packages",
"create.schedule.condition.retrieve_package.summary": "Retrieve packages",
"create.schedule.condition.retrieve_package.status": "Retrieve packages: %1$s",
"create.schedule.condition.retrieve_package.addressed": "with address %1$s",
"create.schedule.condition.deliver_package": "Deliver Packages",
"create.schedule.condition.deliver_package.summary": "Deliver packages",
"create.schedule.condition.deliver_package.status": "Delivering packages",

"create.schedule.condition.player_count": "Players Seated",
"create.schedule.condition.player_count.summary": "%1$s Player",
"create.schedule.condition.player_count.summary_plural": "%1$s Players",
Expand Down
Loading