-
Notifications
You must be signed in to change notification settings - Fork 416
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
first steps toward container item support
- Loading branch information
1 parent
32573c0
commit 9ff9f58
Showing
7 changed files
with
384 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
184 changes: 184 additions & 0 deletions
184
...pi-v1/src/main/java/net/fabricmc/fabric/impl/transfer/item/ContainerComponentStorage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
/* | ||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package net.fabricmc.fabric.impl.transfer.item; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
import org.jetbrains.annotations.UnmodifiableView; | ||
|
||
import net.minecraft.component.ComponentChanges; | ||
import net.minecraft.component.DataComponentTypes; | ||
import net.minecraft.component.type.ContainerComponent; | ||
import net.minecraft.item.ItemStack; | ||
|
||
import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext; | ||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; | ||
import net.fabricmc.fabric.api.transfer.v1.storage.SlottedStorage; | ||
import net.fabricmc.fabric.api.transfer.v1.storage.StoragePreconditions; | ||
import net.fabricmc.fabric.api.transfer.v1.storage.base.CombinedStorage; | ||
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage; | ||
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext; | ||
import net.fabricmc.fabric.mixin.transfer.ContainerComponentAccessor; | ||
|
||
public class ContainerComponentStorage extends CombinedStorage<ItemVariant, SingleSlotStorage<ItemVariant>> implements SlottedStorage<ItemVariant> { | ||
final ContainerItemContext ctx; | ||
|
||
public ContainerComponentStorage(ContainerItemContext ctx, int slots) { | ||
super(Collections.emptyList()); | ||
this.ctx = ctx; | ||
|
||
List<ContainerSlotWrapper> backingList = new ArrayList<>(slots); | ||
|
||
for (int i = 0; i < slots; i++) { | ||
backingList.add(new ContainerSlotWrapper(i)); | ||
} | ||
|
||
parts = Collections.unmodifiableList(backingList); | ||
} | ||
|
||
ContainerComponent container() { | ||
return ctx.getItemVariant().getComponentMap().getOrDefault(DataComponentTypes.CONTAINER, ContainerComponent.DEFAULT); | ||
} | ||
|
||
ContainerComponentAccessor containerAccessor() { | ||
return (ContainerComponentAccessor) (Object) container(); | ||
} | ||
|
||
@Override | ||
public @UnmodifiableView List<SingleSlotStorage<ItemVariant>> getSlots() { | ||
return parts; | ||
} | ||
|
||
@Override | ||
public int getSlotCount() { | ||
return parts.size(); | ||
} | ||
|
||
@Override | ||
public SingleSlotStorage<ItemVariant> getSlot(int slot) { | ||
return parts.get(slot); | ||
} | ||
|
||
private class ContainerSlotWrapper implements SingleSlotStorage<ItemVariant> { | ||
final int slot; | ||
|
||
ContainerSlotWrapper(int slot) { | ||
this.slot = slot; | ||
} | ||
|
||
private ItemStack getStack() { | ||
List<ItemStack> stacks = ContainerComponentStorage.this.containerAccessor().fabric_getStacks(); | ||
|
||
if (stacks.size() <= slot) return ItemStack.EMPTY; | ||
|
||
return stacks.get(slot); | ||
} | ||
|
||
protected boolean setStack(ItemStack stack, TransactionContext transaction) { | ||
List<ItemStack> stacks = ContainerComponentStorage.this.container().stream().collect(Collectors.toList()); | ||
|
||
while (stacks.size() <= slot) stacks.add(ItemStack.EMPTY); | ||
|
||
stacks.set(slot, stack); | ||
|
||
ContainerItemContext ctx = ContainerComponentStorage.this.ctx; | ||
|
||
ItemVariant newVariant = ctx.getItemVariant().withComponentChanges(ComponentChanges.builder() | ||
.add(DataComponentTypes.CONTAINER, ContainerComponent.fromStacks(stacks)) | ||
.build()); | ||
|
||
return ctx.exchange(newVariant, 1, transaction) == 1; | ||
} | ||
|
||
@Override | ||
public long insert(ItemVariant insertedVariant, long maxAmount, TransactionContext transaction) { | ||
StoragePreconditions.notBlankNotNegative(insertedVariant, maxAmount); | ||
|
||
ItemStack currentStack = getStack(); | ||
|
||
if ((insertedVariant.matches(currentStack) || currentStack.isEmpty()) && insertedVariant.getItem().canBeNested()) { | ||
int insertedAmount = (int) Math.min(maxAmount, getCapacity() - currentStack.getCount()); | ||
|
||
if (insertedAmount > 0) { | ||
currentStack = getStack().copy(); | ||
|
||
if (currentStack.isEmpty()) { | ||
currentStack = insertedVariant.toStack(insertedAmount); | ||
} else { | ||
currentStack.increment(insertedAmount); | ||
} | ||
|
||
if (!setStack(currentStack, transaction)) return 0; | ||
|
||
return insertedAmount; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
@Override | ||
public long extract(ItemVariant variant, long maxAmount, TransactionContext transaction) { | ||
StoragePreconditions.notBlankNotNegative(variant, maxAmount); | ||
|
||
ItemStack currentStack = getStack(); | ||
|
||
if (variant.matches(currentStack)) { | ||
int extracted = (int) Math.min(currentStack.getCount(), maxAmount); | ||
|
||
if (extracted > 0) { | ||
currentStack = getStack().copy(); | ||
currentStack.decrement(extracted); | ||
|
||
if (!setStack(currentStack, transaction)) return 0; | ||
|
||
return extracted; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
@Override | ||
public boolean isResourceBlank() { | ||
return getStack().isEmpty(); | ||
} | ||
|
||
@Override | ||
public ItemVariant getResource() { | ||
return ItemVariant.of(getStack()); | ||
} | ||
|
||
@Override | ||
public long getAmount() { | ||
return getStack().getCount(); | ||
} | ||
|
||
@Override | ||
public long getCapacity() { | ||
return getStack().getItem().getMaxCount(); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "ContainerSlotWrapper[%s#%d]".formatted(ContainerComponentStorage.this.ctx.getItemVariant().getRegistryEntry().getIdAsString(), slot); | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
...r-api-v1/src/main/java/net/fabricmc/fabric/mixin/transfer/ContainerComponentAccessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package net.fabricmc.fabric.mixin.transfer; | ||
|
||
import org.spongepowered.asm.mixin.Mixin; | ||
import org.spongepowered.asm.mixin.gen.Accessor; | ||
|
||
import net.minecraft.component.type.ContainerComponent; | ||
import net.minecraft.item.ItemStack; | ||
import net.minecraft.util.collection.DefaultedList; | ||
|
||
@Mixin(ContainerComponent.class) | ||
public interface ContainerComponentAccessor { | ||
@Accessor("stacks") | ||
DefaultedList<ItemStack> fabric_getStacks(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
...-api-v1/src/test/java/net/fabricmc/fabric/test/transfer/unittests/ContainerItemTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package net.fabricmc.fabric.test.transfer.unittests; | ||
|
||
import org.junit.jupiter.api.Assertions; | ||
import org.junit.jupiter.api.BeforeAll; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import net.minecraft.item.ItemStack; | ||
import net.minecraft.item.Items; | ||
|
||
import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext; | ||
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage; | ||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; | ||
import net.fabricmc.fabric.api.transfer.v1.item.base.SingleStackStorage; | ||
import net.fabricmc.fabric.api.transfer.v1.storage.SlottedStorage; | ||
import net.fabricmc.fabric.api.transfer.v1.storage.Storage; | ||
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; | ||
|
||
class ContainerItemTests extends AbstractTransferApiTest { | ||
@BeforeAll | ||
static void beforeAll() { | ||
bootstrap(); | ||
} | ||
|
||
@Test | ||
public void emptyShulkerBox() { | ||
ItemStack stack = new ItemStack(Items.SHULKER_BOX); | ||
Storage<ItemVariant> storage = ItemStorage.ITEM.find(stack, ContainerItemContext.withConstant(stack)); | ||
|
||
Assertions.assertInstanceOf(SlottedStorage.class, storage); | ||
Assertions.assertEquals(27, ((SlottedStorage<ItemVariant>) storage).getSlotCount()); | ||
} | ||
|
||
@Test | ||
public void insertAndExtractShulkerBox() { | ||
var sourceStorage = new SingleStackStorage() { | ||
public ItemStack stack = new ItemStack(Items.SHULKER_BOX); | ||
|
||
@Override | ||
protected ItemStack getStack() { | ||
return stack; | ||
} | ||
|
||
@Override | ||
public void setStack(ItemStack stack) { | ||
this.stack = stack; | ||
} | ||
}; | ||
|
||
Storage<ItemVariant> storage = ItemStorage.ITEM.find(sourceStorage.stack, ContainerItemContext.ofSingleSlot(sourceStorage)); | ||
|
||
Assertions.assertNotNull(storage, "Shulker Box didn't have a Storage<ItemVariant>"); | ||
|
||
try (var tx = Transaction.openOuter()) { | ||
Assertions.assertEquals(20, storage.insert(ItemVariant.of(Items.NETHER_STAR), 20, tx)); | ||
tx.commit(); | ||
} | ||
|
||
try (var tx = Transaction.openOuter()) { | ||
Assertions.assertEquals(20, storage.extract(ItemVariant.of(Items.NETHER_STAR), 64, tx)); | ||
tx.commit(); | ||
} | ||
} | ||
} |
Oops, something went wrong.