Skip to content

Commit 940ebc9

Browse files
committed
Added Bee Port Return Mode toggle in the Bee Port GUI (#136)
- New button that toggles between normal delivery and return mode - In return mode, Robo Bees spawned from that port fly back to their origin port after successful player delivery
1 parent 859c502 commit 940ebc9

13 files changed

Lines changed: 185 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Create: Mobile Packages - v0.7.0 - 1.21.1 - unreleased
44

55
### Additions
66

7+
- Added Bee Port Return Mode toggle in the Bee Port GUI (#136)
8+
- New button that toggles between normal delivery and return mode
9+
- In return mode, Robo Bees spawned from that port fly back to their origin port after successful player delivery
10+
711
- Added Admin/OP Commands for Network Management (#305)
812
- `/cmp network list` - Display all logistics networks with names, player counts, lock status, and owner information
913
- `/cmp network add <player> <networkId>` - Add a player to a network (auto-filters to named networks only)

src/main/java/de/theidler/create_mobile_packages/blocks/bee_port/BeePortBlockEntity.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ public class BeePortBlockEntity extends PackagePortBlockEntity {
6161
private static final int ROBOBEE_INVENTORY_STACK_SIZE = 64;
6262
private UUID placerUUID;
6363

64-
private final ContainerData data = new SimpleContainerData(2);
64+
private final ContainerData data = new SimpleContainerData(3);
6565
private final ItemStackHandler roboBeeInventory = new ItemStackHandler(1);
66+
private boolean beeReturnModeEnabled = false;
6667
private final IItemHandler handler = new IItemHandler() {
6768
@Override
6869
public int getSlots() {
@@ -209,6 +210,7 @@ private synchronized void requestRoboEntity() {
209210
protected void write(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) {
210211
super.write(tag, registries, clientPacket);
211212
tag.put("RoboBeeInventory", roboBeeInventory.serializeNBT(registries));
213+
tag.putBoolean("BeeReturnModeEnabled", beeReturnModeEnabled);
212214
if (placerUUID != null) {
213215
tag.putUUID("PlacerUUID", placerUUID);
214216
}
@@ -220,6 +222,7 @@ protected void read(CompoundTag tag, HolderLookup.Provider registries, boolean c
220222
if (tag.contains("RoboBeeInventory")) {
221223
roboBeeInventory.deserializeNBT(registries, tag.getCompound("RoboBeeInventory"));
222224
}
225+
beeReturnModeEnabled = tag.getBoolean("BeeReturnModeEnabled");
223226
if (tag.contains("PlacerUUID")) {
224227
placerUUID = tag.getUUID("PlacerUUID");
225228
}
@@ -242,6 +245,7 @@ public void tick() {
242245
int minEta = eta.stream().min(Comparator.naturalOrder()).orElse(-1);
243246
this.data.set(0, minEta);
244247
this.data.set(1, eta.isEmpty() ? 0 : 1);
248+
this.data.set(2, beeReturnModeEnabled ? 1 : 0);
245249
}
246250
}
247251

@@ -412,7 +416,7 @@ private void sendDrone(ItemStack itemStack, int slot) {
412416
}
413417
roboSendCooldown = 2;
414418
if (level instanceof ServerLevel serverLevel) {
415-
RoboManager.get(serverLevel).newRobo(serverLevel, itemStack, this.getBlockPos(), this.getLogisticsNetworkId(), 0, this.getBlockPos());
419+
RoboManager.get(serverLevel).newRobo(serverLevel, itemStack, this.getBlockPos(), this.getLogisticsNetworkId(), 0, this.getBlockPos(), beeReturnModeEnabled);
416420
}
417421
inventory.setStackInSlot(slot, ItemStack.EMPTY);
418422
}
@@ -616,4 +620,13 @@ public void handleRequest(RoboRequest request) {
616620
RoboManager.get(serverLevel).newRequestRobo(serverLevel, this.getBlockPos(), request);
617621
}
618622
}
623+
624+
public void setBeeReturnModeEnabled(boolean beeReturnModeEnabled) {
625+
if (this.beeReturnModeEnabled == beeReturnModeEnabled) return;
626+
this.beeReturnModeEnabled = beeReturnModeEnabled;
627+
if (level != null && !level.isClientSide) {
628+
level.blockEntityChanged(worldPosition);
629+
}
630+
setChanged();
631+
}
619632
}

src/main/java/de/theidler/create_mobile_packages/blocks/bee_port/BeePortMenu.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,11 @@ public boolean isBeeOnTravel() {
127127
}
128128
return false;
129129
}
130+
131+
public boolean isBeeReturnModeEnabled() {
132+
if (data != null) {
133+
return data.get(2) == 1;
134+
}
135+
return false;
136+
}
130137
}

src/main/java/de/theidler/create_mobile_packages/blocks/bee_port/BeePortScreen.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import com.simibubi.create.content.logistics.packagePort.PackagePortMenu;
44
import com.simibubi.create.content.logistics.packagePort.PackagePortScreen;
55
import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour;
6+
import com.simibubi.create.foundation.gui.widget.IconButton;
67
import de.theidler.create_mobile_packages.CreateMobilePackages;
8+
import de.theidler.create_mobile_packages.index.CMPIcons;
9+
import net.createmod.catnip.platform.CatnipServices;
710
import net.minecraft.client.gui.GuiGraphics;
811
import net.minecraft.network.chat.Component;
912
import net.minecraft.world.entity.player.Inventory;
@@ -12,16 +15,41 @@
1215

1316
public class BeePortScreen extends PackagePortScreen {
1417

18+
private IconButton enableReturnModeButton;
19+
private IconButton disableReturnModeButton;
20+
1521
public BeePortScreen(PackagePortMenu container, Inventory inv, Component title) {
1622
super(container, inv, title);
1723
}
1824

1925
@Override
2026
protected void init() {
2127
super.init();
28+
int buttonX = getGuiLeft() - 22;
29+
int buttonY = getGuiTop() - 10;
30+
2231
LogisticallyLinkedBehaviour lo = (LogisticallyLinkedBehaviour) menu.contentHolder.getAllBehaviours().stream().filter(b -> b instanceof LogisticallyLinkedBehaviour).findFirst().orElse(null);
2332
if (lo == null) return;
24-
addRenderableWidget(createNetworkSettingsButton(getGuiLeft() - 22, getGuiTop() - 10, lo.freqId));
33+
addRenderableWidget(createNetworkSettingsButton(buttonX, buttonY, lo.freqId));
34+
35+
if (!(menu instanceof BeePortMenu beePortMenu) || !(menu.contentHolder instanceof BeePortBlockEntity beePort))
36+
return;
37+
38+
enableReturnModeButton = new IconButton(buttonX, buttonY + 18, CMPIcons.I_RETURN);
39+
enableReturnModeButton.setToolTip(Component.translatable("tooltip.create_mobile_packages.bee_port.enable_return_mode"));
40+
enableReturnModeButton.withCallback(() -> CatnipServices.NETWORK.sendToServer(
41+
new ToggleBeeReturnModePacket(beePort.getBlockPos(), true)
42+
));
43+
addRenderableWidget(enableReturnModeButton);
44+
45+
disableReturnModeButton = new IconButton(buttonX, buttonY + 18, CMPIcons.I_DIRECT);
46+
disableReturnModeButton.setToolTip(Component.translatable("tooltip.create_mobile_packages.bee_port.disable_return_mode"));
47+
disableReturnModeButton.withCallback(() -> CatnipServices.NETWORK.sendToServer(
48+
new ToggleBeeReturnModePacket(beePort.getBlockPos(), false)
49+
));
50+
addRenderableWidget(disableReturnModeButton);
51+
52+
updateReturnModeButtons(beePortMenu.isBeeReturnModeEnabled());
2553
}
2654

2755
@Override
@@ -30,11 +58,20 @@ protected void renderBg(GuiGraphics graphics, float pPartialTick, int pMouseX, i
3058
graphics.blit(CreateMobilePackages.asResource("textures/gui/bee_port.png"), getGuiLeft(), getGuiTop(), 0, 47, 220, 82);
3159

3260
if (menu instanceof BeePortMenu beePortMenu) {
61+
updateReturnModeButtons(beePortMenu.isBeeReturnModeEnabled());
3362
int eta = beePortMenu.getETA();
3463
Component text = beePortMenu.isBeeOnTravel()
3564
? Component.translatable("create_mobile_packages.bee_port.screen.arrival_time", eta)
3665
: Component.translatable("create_mobile_packages.bee_port.screen.no_bee_on_travel");
3766
graphics.drawString(font, text, getGuiLeft() + 34, getGuiTop() + 64, 0x3D3C48, false);
3867
}
3968
}
69+
70+
private void updateReturnModeButtons(boolean returnModeEnabled) {
71+
if (enableReturnModeButton == null || disableReturnModeButton == null) return;
72+
enableReturnModeButton.visible = !returnModeEnabled;
73+
enableReturnModeButton.active = !returnModeEnabled;
74+
disableReturnModeButton.visible = returnModeEnabled;
75+
disableReturnModeButton.active = returnModeEnabled;
76+
}
4077
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package de.theidler.create_mobile_packages.blocks.bee_port;
2+
3+
import de.theidler.create_mobile_packages.index.CMPPackets;
4+
import net.createmod.catnip.net.base.ServerboundPacketPayload;
5+
import net.minecraft.core.BlockPos;
6+
import net.minecraft.network.RegistryFriendlyByteBuf;
7+
import net.minecraft.network.codec.ByteBufCodecs;
8+
import net.minecraft.network.codec.StreamCodec;
9+
import net.minecraft.server.level.ServerLevel;
10+
import net.minecraft.server.level.ServerPlayer;
11+
12+
public class ToggleBeeReturnModePacket implements ServerboundPacketPayload {
13+
14+
public static final StreamCodec<RegistryFriendlyByteBuf, ToggleBeeReturnModePacket> STREAM_CODEC = StreamCodec.composite(
15+
BlockPos.STREAM_CODEC, packet -> packet.portPos,
16+
ByteBufCodecs.BOOL, packet -> packet.returnModeEnabled,
17+
ToggleBeeReturnModePacket::new
18+
);
19+
20+
private final BlockPos portPos;
21+
private final boolean returnModeEnabled;
22+
23+
public ToggleBeeReturnModePacket(BlockPos portPos, boolean returnModeEnabled) {
24+
this.portPos = portPos;
25+
this.returnModeEnabled = returnModeEnabled;
26+
}
27+
28+
@Override
29+
public void handle(ServerPlayer player) {
30+
if (player == null) return;
31+
ServerLevel serverLevel = player.serverLevel();
32+
if (!(serverLevel.getBlockEntity(portPos) instanceof BeePortBlockEntity beePort)) return;
33+
34+
beePort.setBeeReturnModeEnabled(returnModeEnabled);
35+
}
36+
37+
@Override
38+
public PacketTypeProvider getTypeProvider() {
39+
return CMPPackets.TOGGLE_BEE_RETURN_MODE;
40+
}
41+
}
42+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package de.theidler.create_mobile_packages.index;
2+
3+
import de.theidler.create_mobile_packages.CreateMobilePackages;
4+
import net.createmod.catnip.gui.element.ScreenElement;
5+
import net.minecraft.client.gui.GuiGraphics;
6+
import net.minecraft.resources.ResourceLocation;
7+
import net.neoforged.api.distmarker.Dist;
8+
import net.neoforged.api.distmarker.OnlyIn;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
public class CMPIcons implements ScreenElement {
12+
// from com.simibubi.create.foundation.gui.AllIcons
13+
public static final ResourceLocation ICON_ATLAS = ResourceLocation.fromNamespaceAndPath(CreateMobilePackages.MODID, "textures/gui/icons.png");
14+
public static final int ICON_ATLAS_SIZE = 256;
15+
16+
private static int x = 0, y = -1;
17+
public static final CMPIcons
18+
I_RETURN = newRow(),
19+
I_DIRECT = next();
20+
private final int iconX;
21+
private final int iconY;
22+
23+
24+
public CMPIcons(int x, int y) {
25+
iconX = x * 16;
26+
iconY = y * 16;
27+
}
28+
29+
private static CMPIcons next() {
30+
return new CMPIcons(++x, y);
31+
}
32+
33+
private static CMPIcons newRow() {
34+
return new CMPIcons(x = 0, ++y);
35+
}
36+
37+
@OnlyIn(Dist.CLIENT)
38+
@Override
39+
public void render(@NotNull GuiGraphics graphics, int x, int y) {
40+
graphics.blit(ICON_ATLAS, x, y, 0, iconX, iconY, 16, 16, ICON_ATLAS_SIZE, ICON_ATLAS_SIZE);
41+
}
42+
}

src/main/java/de/theidler/create_mobile_packages/index/CMPPackets.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package de.theidler.create_mobile_packages.index;
22

33
import de.theidler.create_mobile_packages.CreateMobilePackages;
4+
import de.theidler.create_mobile_packages.blocks.bee_port.ToggleBeeReturnModePacket;
45
import de.theidler.create_mobile_packages.items.mobile_packager.ConfirmEditMenuPacket;
56
import de.theidler.create_mobile_packages.items.mobile_packager.OpenEditMenuPacket;
67
import de.theidler.create_mobile_packages.items.portable_stock_ticker.*;
@@ -36,6 +37,7 @@ public enum CMPPackets implements BasePacketPayload.PacketTypeProvider {
3637
REQUEST_PLAYER_NETWORKS(RequestPlayerNetworksPacket.class, RequestPlayerNetworksPacket.STREAM_CODEC),
3738
OPEN_TRASH_MENU(OpenTrashMenuPacket.class, OpenTrashMenuPacket.STREAM_CODEC),
3839
SYNC_TRASH_ADDRESS(SyncTrashAddressPacket.class, SyncTrashAddressPacket.STREAM_CODEC),
40+
TOGGLE_BEE_RETURN_MODE(ToggleBeeReturnModePacket.class, ToggleBeeReturnModePacket.STREAM_CODEC),
3941

4042
// Server to Client
4143
BIG_ITEM_STACK_LIST(GenericStackListPacket.class, GenericStackListPacket.STREAM_CODEC),

src/main/java/de/theidler/create_mobile_packages/items/robo_bee/RoboBeeItem.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public RoboBeeItem(Properties pProperties) {
4848
if (level instanceof ServerLevel serverLevel) {
4949
UUID networkId = networkFromStack(context.getItemInHand());
5050
UUID finalNetworkId = networkId != null ? networkId : UUID.randomUUID();
51-
RoboManager.get(serverLevel).newRobo(serverLevel, packageItem, pos, finalNetworkId, 1, null);
51+
RoboManager.get(serverLevel).newRobo(serverLevel, packageItem, pos, finalNetworkId, 1, null, false);
5252
}
5353
context.getItemInHand().shrink(1);
5454
return InteractionResult.SUCCESS;

src/main/java/de/theidler/create_mobile_packages/robo/RoboManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,12 @@ private boolean hasActiveTrashRequest(UUID playerId, UUID networkId) {
245245
return false;
246246
}
247247

248-
public UUID newRobo(ServerLevel level, ItemStack itemStack, BlockPos spawnPos, UUID logisticsNetworkId, float packageHeightScale, @Nullable BlockPos homePort) {
248+
public UUID newRobo(ServerLevel level, ItemStack itemStack, BlockPos spawnPos, UUID logisticsNetworkId, float packageHeightScale, @Nullable BlockPos homePort, boolean returnToHomeAfterDelivery) {
249249
UUID id = UUID.randomUUID();
250250
VirtualRobo robo = new VirtualRobo(level, id, itemStack, spawnPos, logisticsNetworkId);
251251
robo.setPackageHeightScale(packageHeightScale);
252252
robo.setHomePortPos(homePort);
253+
robo.setReturnToHomeAfterDelivery(returnToHomeAfterDelivery);
253254
this.add(robo);
254255
setDirty();
255256
return id;

src/main/java/de/theidler/create_mobile_packages/robo/VirtualRobo.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class VirtualRobo {
3939
private float packageHeightScale;
4040
private RoboRequest request = null;
4141
private @Nullable BlockPos homePortPos;
42+
private boolean returnToHomeAfterDelivery;
4243

4344
public VirtualRobo(ServerLevel level, UUID id, ItemStack itemStack, BlockPos spawnPos, UUID logisticsNetworkId) {
4445
this.id = id;
@@ -64,6 +65,10 @@ public static VirtualRobo deserializeNBT(ServerLevel level, CompoundTag roboTag)
6465

6566
VirtualRobo virtualRobo = new VirtualRobo(level, id, itemStack, BlockPos.containing(pos), logisticsNetworkId);
6667
virtualRobo.setSpeed(speed);
68+
if (roboTag.contains("homePortPos")) {
69+
virtualRobo.setHomePortPos(BlockPos.of(roboTag.getLong("homePortPos")));
70+
}
71+
virtualRobo.setReturnToHomeAfterDelivery(roboTag.getBoolean("returnToHomeAfterDelivery"));
6772
if (!virtualRobo.getItemStack().isEmpty()) {
6873
virtualRobo.setPackageHeightScale(1.0f);
6974
}
@@ -105,6 +110,17 @@ private void updateTarget() {
105110
// if the target is still valid and in the correct network, do nothing
106111
if (target != null && target.isValid(this)) return;
107112

113+
// Return-mode should prefer the original home port after successful delivery.
114+
if (shouldReturnToHomePort()) {
115+
BeePortBlockEntity homePort = CMPHelper.getPortAtPos(serverLevel, homePortPos);
116+
if (homePort != null) {
117+
target = new BeePortBlockEntityTarget(homePort);
118+
if (target.isValid(this)) {
119+
return;
120+
}
121+
}
122+
}
123+
108124
// try finding a Player first
109125
target = PlayerTarget.fromAddress(serverLevel, targetAddress, logisticsNetworkId);
110126
if (target != null && target.isValid(this)) {
@@ -222,6 +238,10 @@ public CompoundTag serializeNBT() {
222238
if (!getItemStack().isEmpty()) {
223239
tag.put("itemStack", getItemStack().save(serverLevel.registryAccess(), new CompoundTag()));
224240
}
241+
if (homePortPos != null) {
242+
tag.putLong("homePortPos", homePortPos.asLong());
243+
}
244+
tag.putBoolean("returnToHomeAfterDelivery", returnToHomeAfterDelivery);
225245
return tag;
226246
}
227247

@@ -359,4 +379,12 @@ public void setHomePortPos(@Nullable BlockPos homePort) {
359379
if (homePort == null) return;
360380
this.homePortPos = homePort;
361381
}
382+
383+
public boolean shouldReturnToHomePort() {
384+
return returnToHomeAfterDelivery && request == null && (itemStack == null || itemStack.isEmpty());
385+
}
386+
387+
public void setReturnToHomeAfterDelivery(boolean returnToHomeAfterDelivery) {
388+
this.returnToHomeAfterDelivery = returnToHomeAfterDelivery;
389+
}
362390
}

0 commit comments

Comments
 (0)