Inventory10Slots
需求分析
众所周知,MC中的物品栏界面的格子数量总是9的倍数
但是你偶然间发现,合成界面拥有一个额外的成品槽
如果这个槽位也能存放物品,你将得到一个十个格子的物品栏
代码
该示例位于MzLibDemo的Inventory10Slots模块中
结构
首先我们需要一个类继承了UIWindow
java
public static class UIInventory10Slots extends UIWindow
{
public UIInventory10Slots()
{
super(UnionWindowType.CRAFTING, 10);
}
@Override
public Text getTitle(EntityPlayer player)
{
return Text.literal("10个格子的物品栏");
}
}
调用父类构造器,窗口类型是合成界面,物品栏的size是10
然后我们简单注册一个命令让玩家打开这个窗口,比较简单,这里不做说明
覆写quickMove
其实到这一步玩家已经可以往这个物品栏里存放东西了,但是在quickMove(按住shift点击物品)时会有点小问题
当玩家要快速移动背包中的物品时quickMove的默认行为是优先移动到0号槽位
但由于0号槽位是成品槽,客户端认为物品会优先移动到从1开始的槽位,导致同步时出现一点问题(物品会在错误的位置闪一下)
因此我们覆写quickMove方法,使得默认行为与客户端一致,即先考虑1 8,最后再考虑0号位
java
@Override
public ItemStack quickMove(WindowUIWindow window, EntityPlayer player, int index)
{
int upperSize = window.getSlots().size()-36; // 其实就是10
// 从物品栏移动到背包不用管,使用默认行为
if(index<upperSize)
return super.quickMove(window, player, index);
WindowSlot slot = window.getSlot(index);
// 不做更改时,返回ItemStack.empty()
if(!slot.isPresent() || slot.getItemStack().isEmpty())
return ItemStack.empty();
ItemStack is = slot.getItemStack();
ItemStack copy = is.copy();
ItemStack result = ItemStack.empty();
// 先考虑放进1~8
if(window.placeIn(is, 1, upperSize, false))
result = copy; // 如果更改,返回值是原始拷贝
// 再考虑成品槽
if(window.placeIn(is, 0, 1, false))
result = copy;
// markDirty
if(!result.isEmpty())
{
if(is.isEmpty())
slot.setItemStackByPlayer(ItemStack.empty());
else
slot.markDirty();
}
return result;
}
经过测试,将背包物品快速移动到物品栏确实没问题了,但从成品槽中快速拿出物品其实不是很同步
在客户端默认行为中,从成品槽快速拿出物品会倒序放入背包,即placeIn的最后一个参数应该设置成false
因此我们还要考虑从物品栏移动到背包的情况
java
@Override
public ItemStack quickMove(WindowUIWindow window, EntityPlayer player, int index)
{
WindowSlot slot = window.getSlot(index);
if(!slot.isPresent() || slot.getItemStack().isEmpty())
return ItemStack.empty();
ItemStack is = slot.getItemStack();
ItemStack copy = is.copy();
ItemStack result = ItemStack.empty();
int upperSize = window.getSlots().size()-36;
if(index<upperSize) // 点击的是物品栏,移动到背包
{
if(window.placeIn(is, upperSize, window.getSlots().size(), index==0 /*仅当成品槽(0)时inverted为true*/))
result = copy;
}
else // 否则从背包移动到物品栏
{
if(window.placeIn(is, 1, upperSize, false))
result = copy;
if(window.placeIn(is, 0, 1, false))
result = copy;
}
if(!result.isEmpty())
{
if(is.isEmpty())
slot.setItemStackByPlayer(ItemStack.empty());
else
slot.markDirty();
}
return result;
}
完成
总结
通过这个demo,你知道如何覆写UIWindow#quickMove,并应该将效果尽量做得与客户端同步