Search in sources :

Example 6 with InventoryDimension

use of org.spongepowered.api.item.inventory.property.InventoryDimension in project LanternServer by LanternPowered.

the class LanternInventoryArchetypeBuilder method build.

@Override
public InventoryArchetype build(String id, String name) {
    final int index = id.indexOf(':');
    final String pluginId;
    if (index == -1) {
        pluginId = InternalPluginsInfo.Implementation.IDENTIFIER;
    } else {
        pluginId = id.substring(0, index);
        id = id.substring(index + 1);
    }
    final Map<Class<?>, InventoryProperty<?, ?>> properties = new HashMap<>(this.properties);
    final InventoryDimension inventoryDimension = (InventoryDimension) properties.remove(InventoryDimension.class);
    final InventoryCapacity inventoryCapacity = (InventoryCapacity) properties.remove(InventoryCapacity.class);
    int size = -1;
    if (inventoryDimension != null) {
        final int targetRows = inventoryDimension.getRows();
        final int targetColumns = inventoryDimension.getColumns();
        size = targetRows * targetColumns;
        if (inventoryCapacity != null && size != inventoryCapacity.getValue()) {
            throw new IllegalStateException("The InventoryCapacity " + inventoryCapacity.getValue() + " mismatches the InventoryDimension " + "slots quantity: " + targetRows + " * " + targetColumns + " = " + size);
        }
    } else if (inventoryCapacity != null) {
        size = inventoryCapacity.getValue();
    }
    // A base archetype is provided to create slots
    if (this.baseArchetype != null) {
        if (this.baseArchetype.getBuilder() instanceof AbstractSlot.Builder) {
            return buildArchetype(pluginId, id, properties, this.baseArchetype);
        } else if (this.baseArchetype.getBuilder() instanceof AbstractGridInventory.Builder) {
            final AbstractGridInventory.Builder builder = (AbstractGridInventory.Builder) this.baseArchetype.getBuilder().copy();
            if (inventoryDimension != null) {
                builder.expand(inventoryDimension.getColumns(), inventoryDimension.getRows());
            }
            if (builder instanceof AbstractGridInventory.SlotsBuilder) {
                final AbstractGridInventory.SlotsBuilder slotsBuilder = (AbstractGridInventory.SlotsBuilder) builder;
                for (LanternInventoryArchetype<?> archetype : this.archetypes) {
                    if (!(archetype.getBuilder() instanceof AbstractSlot.Builder)) {
                        throw new IllegalStateException("Only slot archetypes can be added to a slot based grid builder.");
                    }
                    slotsBuilder.slot(archetype);
                }
                applyProperties(properties, builder);
                return slotsBuilder.buildArchetype(pluginId, id);
            } else if (builder instanceof AbstractGridInventory.RowsBuilder) {
                final AbstractGridInventory.RowsBuilder rowsBuilder = (AbstractGridInventory.RowsBuilder) builder;
                for (LanternInventoryArchetype<?> archetype : this.archetypes) {
                    final Class<?> inventoryType = builder.constructor.getType();
                    if (InventoryRow.class.isAssignableFrom(inventoryType) || GridInventory.class.isAssignableFrom(inventoryType)) {
                        rowsBuilder.inventory(archetype);
                    } else {
                        throw new IllegalStateException("Only rows or grids can be added to a rows based grid builder.");
                    }
                }
                applyProperties(properties, builder);
                return rowsBuilder.buildArchetype(pluginId, id);
            } else if (builder instanceof AbstractGridInventory.ColumnsBuilder) {
                final AbstractGridInventory.ColumnsBuilder columnsBuilder = (AbstractGridInventory.ColumnsBuilder) builder;
                for (LanternInventoryArchetype<?> archetype : this.archetypes) {
                    final Class<?> inventoryType = builder.constructor.getType();
                    if (InventoryColumn.class.isAssignableFrom(inventoryType) || GridInventory.class.isAssignableFrom(inventoryType)) {
                        columnsBuilder.inventory(archetype);
                    } else {
                        throw new IllegalStateException("Only columns or grids can be added to a columns based grid builder.");
                    }
                }
                applyProperties(properties, builder);
                return columnsBuilder.buildArchetype(pluginId, id);
            } else {
                throw new IllegalStateException();
            }
        } else if (this.baseArchetype.getBuilder() instanceof AbstractOrderedInventory.Builder) {
            final AbstractOrderedInventory.Builder builder = (AbstractOrderedInventory.Builder) this.baseArchetype.getBuilder().copy();
            if (inventoryDimension != null) {
                final Class<?> inventoryType = builder.constructor.getType();
                if (InventoryColumn.class.isAssignableFrom(inventoryType) && inventoryDimension.getColumns() != 1) {
                    throw new IllegalStateException("A inventory column can only have one column, not " + inventoryDimension.getColumns() + " specified by the InventoryDimension.");
                } else if (InventoryRow.class.isAssignableFrom(inventoryType) && inventoryDimension.getRows() != 1) {
                    throw new IllegalStateException("A inventory row can only have one row, not " + inventoryDimension.getRows() + " specified by the InventoryDimension.");
                }
                builder.expand(inventoryDimension.getColumns() * inventoryDimension.getRows());
            } else if (inventoryCapacity != null) {
                builder.expand(inventoryCapacity.getValue());
            }
            for (LanternInventoryArchetype<?> archetype : this.archetypes) {
                if (!(archetype.getBuilder() instanceof AbstractSlot.Builder)) {
                    throw new IllegalStateException("Only slot archetypes can be added to a slot based builder.");
                }
                builder.addLast(archetype);
            }
            applyProperties(properties, builder);
            return builder.buildArchetype(pluginId, id);
        } else if (this.baseArchetype.getBuilder() instanceof AbstractOrderedInventory.Builder) {
            if (inventoryDimension != null) {
                throw new IllegalStateException("A InventoryDimension cannot be applied to a ordered children inventory.");
            }
            final AbstractOrderedInventory.Builder builder = (AbstractOrderedInventory.Builder) this.baseArchetype.getBuilder().copy();
            for (LanternInventoryArchetype<?> archetype : this.archetypes) {
                builder.addLast(archetype);
            }
            applyProperties(properties, builder);
            final LanternInventoryArchetype<?> archetype = builder.buildArchetype(pluginId, id);
            if (inventoryCapacity != null) {
                final AbstractInventory inventory = archetype.build();
                if (inventory.capacity() != inventoryCapacity.getValue()) {
                    throw new IllegalStateException("InventoryCapacity mismatch with the size of the resulting inventory. Got " + inventory.capacity() + ", but expected " + inventoryCapacity.getValue());
                }
            }
            return archetype;
        }
    }
    // A slot
    if (size == 1) {
        final LanternInventoryArchetype<?> archetype;
        if (!this.archetypes.isEmpty()) {
            archetype = this.archetypes.get(0);
            if (this.archetypes.size() != 1 || !(archetype.getBuilder() instanceof AbstractSlot.Builder)) {
                throw new IllegalStateException("A Inventory with a InventoryCapacity of one can only be one slot.");
            }
        } else {
            archetype = VanillaInventoryArchetypes.SLOT;
        }
        return buildArchetype(pluginId, name, properties, archetype);
    } else if (size == 0 || this.archetypes.isEmpty()) {
        // A empty archetype
        return new UnknownInventoryArchetype(pluginId, id);
    }
    if (inventoryDimension != null) {
        final int targetRows = inventoryDimension.getRows();
        final int targetColumns = inventoryDimension.getColumns();
        // There are two cases to handle a inventory dimension property, if there are only slots,
        // just generate a grid/column/row with those slots. Otherwise try to merge all the columns/rows/grid
        // into the target dimension
        // Try to generate a slots grid
        boolean allSlots = true;
        for (LanternInventoryArchetype<?> archetype : this.archetypes) {
            if (!(archetype.getBuilder() instanceof AbstractSlot.Builder)) {
                allSlots = false;
                break;
            }
        }
        if (allSlots) {
            if (this.archetypes.size() != size) {
                throw new IllegalStateException("Not enough slots are found (" + this.archetypes.size() + ") to reach the capacity of " + size);
            }
            if (targetColumns == 1 || targetRows == 1) {
                final AbstractOrderedInventory.Builder<LanternOrderedInventory> builder = AbstractOrderedInventory.builder();
                for (LanternInventoryArchetype<?> archetype : this.archetypes) {
                    builder.addLast((LanternInventoryArchetype<? extends AbstractSlot>) archetype);
                }
                applyProperties(properties, builder);
                if (targetColumns == 1) {
                    return builder.type(LanternInventoryColumn.class).buildArchetype(pluginId, id);
                } else {
                    return builder.type(LanternInventoryRow.class).buildArchetype(pluginId, id);
                }
            } else {
                final AbstractGridInventory.SlotsBuilder<AbstractGridInventory> builder = AbstractGridInventory.slotsBuilder();
                for (int y = 0; y < targetRows; y++) {
                    for (int x = 0; x < targetColumns; x++) {
                        builder.slot(x, y, (LanternInventoryArchetype<? extends AbstractSlot>) this.archetypes.get(y * targetColumns + x));
                    }
                }
                applyProperties(properties, builder);
                return builder.buildArchetype(pluginId, id);
            }
        }
        // Try to copy a row archetype
        if ((targetColumns == 1 || targetRows == 1) && this.archetypes.size() == 1) {
            final LanternInventoryArchetype<?> archetype = this.archetypes.get(0);
            if (archetype.getBuilder() instanceof AbstractOrderedInventory.Builder) {
                final AbstractOrderedInventory.Builder<AbstractOrderedInventory> builder = (AbstractOrderedInventory.Builder<AbstractOrderedInventory>) archetype.getBuilder().copy();
                final Class<?> inventoryType = ((AbstractOrderedInventory.Builder) archetype.getBuilder()).constructor.getType();
                if (targetRows == 1 && !(InventoryRow.class.isAssignableFrom(inventoryType))) {
                    builder.type(LanternInventoryRow.class);
                } else if (targetColumns == 1 && !(InventoryColumn.class.isAssignableFrom(inventoryType))) {
                    builder.type(LanternInventoryColumn.class);
                }
                applyProperties(properties, builder);
                return builder.buildArchetype(pluginId, id);
            }
        }
        // Try to construct the grid from rows/columns/grids
        int rows = 0;
        int columns = 0;
        boolean fixedRows = false;
        boolean fixedColumns = false;
        for (LanternInventoryArchetype<?> archetype : this.archetypes) {
            // Retrieve the columns/rows from the archetype, if present
            int rows1 = 0;
            int columns1 = 0;
            if (archetype.getBuilder() instanceof AbstractGridInventory.Builder) {
                final AbstractGridInventory.Builder builder = (AbstractGridInventory.Builder) archetype.getBuilder();
                rows1 = builder.rows;
                columns1 = builder.columns;
            } else if (archetype.getBuilder() instanceof AbstractOrderedInventory.Builder) {
                final Class<?> inventoryType = ((AbstractOrderedInventory.Builder) archetype.getBuilder()).constructor.getType();
                if (InventoryRow.class.isAssignableFrom(inventoryType)) {
                    columns1 = ((AbstractOrderedInventory.Builder) archetype.getBuilder()).slots;
                    rows1 = 1;
                } else if (InventoryColumn.class.isAssignableFrom(inventoryType)) {
                    rows1 = ((AbstractOrderedInventory.Builder) archetype.getBuilder()).slots;
                    columns1 = 1;
                }
            }
            if (rows1 == 0) {
                rows = 0;
                break;
            }
            if (rows1 == targetRows) {
                if (fixedColumns) {
                    rows = 0;
                    break;
                }
                fixedRows = true;
                rows = rows1;
                columns += columns1;
            } else if (columns1 == targetColumns) {
                if (fixedRows) {
                    rows = 0;
                    break;
                }
                fixedColumns = true;
                columns = columns1;
                rows += rows1;
            } else {
                rows = 0;
                break;
            }
        }
        if (rows != targetRows || columns != targetColumns) {
            throw new IllegalArgumentException("Unable to construct a inventory grid from the inventory archetypes.");
        }
        if (fixedColumns) {
            int y = 0;
            final AbstractGridInventory.RowsBuilder<AbstractGridInventory> builder = AbstractGridInventory.rowsBuilder();
            for (LanternInventoryArchetype<?> archetype : this.archetypes) {
                if (archetype.getBuilder() instanceof AbstractGridInventory.Builder) {
                    builder.grid(y, (LanternInventoryArchetype) archetype);
                    y += ((AbstractGridInventory.Builder) archetype.getBuilder()).rows;
                } else {
                    builder.row(y, (LanternInventoryArchetype) archetype);
                    y++;
                }
            }
            applyProperties(properties, builder);
            return builder.type(LanternGridInventory.class).buildArchetype(pluginId, id);
        } else {
            int x = 0;
            final AbstractGridInventory.ColumnsBuilder<AbstractGridInventory> builder = AbstractGridInventory.columnsBuilder();
            for (LanternInventoryArchetype<?> archetype : this.archetypes) {
                if (archetype.getBuilder() instanceof AbstractGridInventory.Builder) {
                    builder.grid(x, (LanternInventoryArchetype) archetype);
                    x += ((AbstractGridInventory.Builder) archetype.getBuilder()).columns;
                } else {
                    builder.column(x, (LanternInventoryArchetype) archetype);
                    x++;
                }
            }
            applyProperties(properties, builder);
            return builder.type(LanternGridInventory.class).buildArchetype(pluginId, id);
        }
    }
    // Just generate a ordered children inventory
    final AbstractOrderedInventory.Builder<LanternOrderedInventory> builder = AbstractOrderedInventory.builder();
    for (LanternInventoryArchetype<?> archetype : this.archetypes) {
        builder.addLast((LanternInventoryArchetype<? extends AbstractMutableInventory>) archetype);
    }
    applyProperties(properties, builder);
    return builder.buildArchetype(pluginId, id);
}
Also used : LanternOrderedInventory(org.lanternpowered.server.inventory.type.LanternOrderedInventory) InventoryCapacity(org.spongepowered.api.item.inventory.property.InventoryCapacity) HashMap(java.util.HashMap) LanternInventoryColumn(org.lanternpowered.server.inventory.type.LanternInventoryColumn) InventoryProperty(org.spongepowered.api.item.inventory.InventoryProperty) InventoryDimension(org.spongepowered.api.item.inventory.property.InventoryDimension) LanternGridInventory(org.lanternpowered.server.inventory.type.LanternGridInventory) GridInventory(org.spongepowered.api.item.inventory.type.GridInventory) LanternInventoryRow(org.lanternpowered.server.inventory.type.LanternInventoryRow) LanternGridInventory(org.lanternpowered.server.inventory.type.LanternGridInventory) LanternInventoryRow(org.lanternpowered.server.inventory.type.LanternInventoryRow) InventoryRow(org.spongepowered.api.item.inventory.type.InventoryRow) InventoryColumn(org.spongepowered.api.item.inventory.type.InventoryColumn) LanternInventoryColumn(org.lanternpowered.server.inventory.type.LanternInventoryColumn)

Aggregations

InventoryDimension (org.spongepowered.api.item.inventory.property.InventoryDimension)6 InventoryCapacity (org.spongepowered.api.item.inventory.property.InventoryCapacity)4 InventoryArchetype (org.spongepowered.api.item.inventory.InventoryArchetype)2 Vector2i (com.flowpowered.math.vector.Vector2i)1 HashMap (java.util.HashMap)1 UUID (java.util.UUID)1 IMerchant (net.minecraft.entity.IMerchant)1 AbstractHorse (net.minecraft.entity.passive.AbstractHorse)1 ContainerBeacon (net.minecraft.inventory.ContainerBeacon)1 ContainerBrewingStand (net.minecraft.inventory.ContainerBrewingStand)1 ContainerChest (net.minecraft.inventory.ContainerChest)1 ContainerDispenser (net.minecraft.inventory.ContainerDispenser)1 ContainerEnchantment (net.minecraft.inventory.ContainerEnchantment)1 ContainerFurnace (net.minecraft.inventory.ContainerFurnace)1 ContainerHopper (net.minecraft.inventory.ContainerHopper)1 ContainerHorseInventory (net.minecraft.inventory.ContainerHorseInventory)1 ContainerMerchant (net.minecraft.inventory.ContainerMerchant)1 ContainerRepair (net.minecraft.inventory.ContainerRepair)1 ContainerWorkbench (net.minecraft.inventory.ContainerWorkbench)1 IInventory (net.minecraft.inventory.IInventory)1