/*
* This file is part of LanternServer, licensed under the MIT License (MIT).
*
* Copyright (c) LanternPowered <https://www.lanternpowered.org>
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the Software), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.lanternpowered.server.inventory.entity;
import static com.google.common.base.Preconditions.checkNotNull;
import org.lanternpowered.server.inventory.AbstractChildrenInventory;
import org.lanternpowered.server.inventory.AbstractInventory;
import org.lanternpowered.server.inventory.AbstractMutableInventory;
import org.lanternpowered.server.inventory.LanternCraftingInventory;
import org.lanternpowered.server.inventory.LanternEquipmentInventory;
import org.lanternpowered.server.inventory.LanternGridInventory;
import org.lanternpowered.server.inventory.LanternOrderedInventory;
import org.lanternpowered.server.inventory.slot.LanternCraftingInput;
import org.lanternpowered.server.inventory.slot.LanternCraftingOutput;
import org.lanternpowered.server.inventory.slot.LanternEquipmentSlot;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.item.inventory.Inventory;
import org.spongepowered.api.item.inventory.entity.PlayerInventory;
import org.spongepowered.api.item.inventory.equipment.EquipmentTypes;
import org.spongepowered.api.text.translation.Translation;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
public class LanternPlayerInventory extends LanternOrderedInventory implements PlayerInventory {
@Nullable private final WeakReference<Player> player;
private LanternHotbar hotbar;
private final LanternEquipmentInventory equipmentInventory;
private final HumanMainInventory mainInventory;
private final OffHandSlot offHandSlot;
private final Map<HumanInventoryView, AbstractMutableInventory> inventoryViews = new EnumMap<>(HumanInventoryView.class);
public LanternPlayerInventory(@Nullable Inventory parent, @Nullable Translation name, @Nullable Player player) {
super(parent, name);
this.player = player == null ? null : new WeakReference<>(player);
this.registerChild(new LanternCraftingInventory(this) {
{
registerSlot(new LanternCraftingOutput(this));
registerChild(new LanternGridInventory(this) {
{
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 2; x++) {
registerSlotAt(x, y, new LanternCraftingInput(this));
}
}
finalizeContent();
}
});
finalizeContent();
}
});
this.equipmentInventory = this.registerChild(new LanternEquipmentInventory(this, player) {
{
registerSlot(new LanternEquipmentSlot(this, EquipmentTypes.HEADWEAR));
registerSlot(new LanternEquipmentSlot(this, EquipmentTypes.CHESTPLATE));
registerSlot(new LanternEquipmentSlot(this, EquipmentTypes.LEGGINGS));
registerSlot(new LanternEquipmentSlot(this, EquipmentTypes.BOOTS));
this.slots.forEach(slot -> slot.setMaxStackSize(1));
finalizeContent();
}
});
this.mainInventory = this.registerChild(new HumanMainInventory(this, null) {
{
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 9; x++) {
this.registerSlotAt(x, y);
}
}
hotbar = this.registerRow(3, new LanternHotbar(this) {
{
for (int x = 0; x < 9; x++) {
this.registerSlotAt(x);
}
this.finalizeContent();
}
});
finalizeContent();
prioritizeChild(hotbar);
}
});
this.offHandSlot = this.registerChild(new OffHandSlot(this, null));
// Generate inventory views
this.inventoryViews.put(HumanInventoryView.MAIN,
this.generateMainView(this, this.mainInventory));
this.inventoryViews.put(HumanInventoryView.REVERSE_MAIN_AND_HOTBAR,
this.generateReverseMainAndHotbarView(this, this.mainInventory));
final AbstractMutableInventory priorityMainAndHotbarView = this.generatePriorityMainAndHotbarView(this, this.mainInventory);
this.inventoryViews.put(HumanInventoryView.PRIORITY_MAIN_AND_HOTBAR,
priorityMainAndHotbarView);
this.inventoryViews.put(HumanInventoryView.ALL_PRIORITY_MAIN,
this.generateAllPriorityMainView(this.mainInventory));
this.inventoryViews.put(HumanInventoryView.RAW_INVENTORY,
this.generateRawInventoryView(this.mainInventory, this.equipmentInventory, this.offHandSlot));
// This is the default views/inventories
this.inventoryViews.put(HumanInventoryView.MAIN_AND_PRIORITY_HOTBAR, this.mainInventory);
this.inventoryViews.put(HumanInventoryView.HOTBAR, this.hotbar);
}
private AbstractMutableInventory generateRawInventoryView(HumanMainInventory mainInventory,
LanternEquipmentInventory equipmentInventory, OffHandSlot offHandSlot) {
return new LanternOrderedInventory(null, null) {
{
registerChild(new HumanMainInventory(this, null) {
{
registerRow(0, hotbar);
for (int i = 0; i < 3; i++) {
registerRow(i + 1, mainInventory.getRow(i).get());
}
}
});
registerChild(equipmentInventory);
registerChild(offHandSlot);
}
};
}
private AbstractMutableInventory generateMainView(@Nullable Inventory parent, HumanMainInventory mainInventory) {
final List<AbstractInventory> children = new ArrayList<>(mainInventory.getChildren());
children.removeAll(this.hotbar.getChildren());
return new AbstractChildrenInventory(parent, null, children);
}
private AbstractMutableInventory generateReverseMainAndHotbarView(@Nullable Inventory parent, HumanMainInventory mainInventory) {
final List<AbstractInventory> children = new ArrayList<>(mainInventory.getChildren());
final List<AbstractInventory> hotbarSlots = new ArrayList<>(this.hotbar.getChildren());
children.removeAll(hotbarSlots);
Collections.reverse(children);
Collections.reverse(hotbarSlots);
children.addAll(0, hotbarSlots);
return new AbstractChildrenInventory(parent, null, children);
}
private AbstractMutableInventory generatePriorityMainAndHotbarView(@Nullable Inventory parent, HumanMainInventory mainInventory) {
final List<AbstractInventory> children = new ArrayList<>(mainInventory.getChildren());
final List<AbstractInventory> hotbarSlots = new ArrayList<>(this.hotbar.getChildren());
children.removeAll(hotbarSlots);
children.addAll(hotbarSlots);
return new AbstractChildrenInventory(parent, null, children);
}
private AbstractMutableInventory generateAllPriorityMainView(HumanMainInventory mainInventory) {
final List<AbstractInventory> children = new ArrayList<>(this.getChildren());
return new AbstractChildrenInventory(null, null) {
{
children.set(children.indexOf(mainInventory), generatePriorityMainAndHotbarView(this, mainInventory));
children.forEach(this::registerChild);
}
};
}
/**
* Gets the {@link Inventory} for the specified
* {@link HumanInventoryView}.
*
* @param inventoryView The inventory view
* @return The inventory
*/
public AbstractMutableInventory getInventoryView(HumanInventoryView inventoryView) {
return this.inventoryViews.get(checkNotNull(inventoryView, "inventoryView"));
}
@Override
public LanternHotbar getHotbar() {
return this.hotbar;
}
@Override
public HumanMainInventory getMain() {
return this.mainInventory;
}
@Override
public LanternEquipmentInventory getEquipment() {
return this.equipmentInventory;
}
@Override
public OffHandSlot getOffhand() {
return this.offHandSlot;
}
@Override
public Optional<Player> getCarrier() {
return this.player == null ? Optional.empty() : Optional.ofNullable(this.player.get());
}
}