forked from GeyserMC/Geyser
Work on villager trading
This commit is contained in:
parent
30e38b3a2f
commit
e2d46c3d49
4 changed files with 72 additions and 85 deletions
|
@ -156,12 +156,6 @@ public class GeyserSession implements CommandSender {
|
||||||
@Setter
|
@Setter
|
||||||
private Vector3i lastInteractionPosition;
|
private Vector3i lastInteractionPosition;
|
||||||
|
|
||||||
@Setter
|
|
||||||
private ItemStack firstTradeSlot;
|
|
||||||
|
|
||||||
@Setter
|
|
||||||
private ItemStack secondTradeSlot;
|
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private boolean switchingDimension = false;
|
private boolean switchingDimension = false;
|
||||||
private boolean manyDimPackets = false;
|
private boolean manyDimPackets = false;
|
||||||
|
|
|
@ -26,7 +26,12 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.bedrock;
|
package org.geysermc.connector.network.translators.bedrock;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.window.VillagerTrade;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.window.WindowType;
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientSelectTradePacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
||||||
|
import org.geysermc.connector.entity.living.merchant.VillagerEntity;
|
||||||
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
|
@ -41,6 +46,23 @@ public class BedrockEntityEventTranslator extends PacketTranslator<EntityEventPa
|
||||||
case EATING_ITEM:
|
case EATING_ITEM:
|
||||||
session.sendUpstreamPacket(packet);
|
session.sendUpstreamPacket(packet);
|
||||||
return;
|
return;
|
||||||
|
case COMPLETE_TRADE:
|
||||||
|
ClientSelectTradePacket selectTradePacket = new ClientSelectTradePacket(packet.getData());
|
||||||
|
session.getDownstream().getSession().send(selectTradePacket);
|
||||||
|
|
||||||
|
VillagerEntity villager = (VillagerEntity) session.getEntityCache().getEntityByGeyserId(session.getLastInteractedVillagerEid());
|
||||||
|
if (villager == null) {
|
||||||
|
session.getConnector().getLogger().debug("Could not find villager with entity id: " + session.getLastInteractedVillagerEid());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Inventory openInventory = session.getInventoryCache().getOpenInventory();
|
||||||
|
if (openInventory != null && openInventory.getWindowType() == WindowType.MERCHANT) {
|
||||||
|
if (packet.getData() > 0 && packet.getData() < villager.getVillagerTrades().length) {
|
||||||
|
VillagerTrade trade = villager.getVillagerTrades()[packet.getData()];
|
||||||
|
openInventory.setItem(2, trade.getOutput());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
session.getConnector().getLogger().debug("Did not translate incoming EntityEventPacket: " + packet.toString());
|
session.getConnector().getLogger().debug("Did not translate incoming EntityEventPacket: " + packet.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,18 +26,11 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.inventory;
|
package org.geysermc.connector.network.translators.inventory;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.window.ClickItemParam;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.window.VillagerTrade;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.window.WindowAction;
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientSelectTradePacket;
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
||||||
import com.nukkitx.protocol.bedrock.data.InventoryActionData;
|
import com.nukkitx.protocol.bedrock.data.InventoryActionData;
|
||||||
import org.geysermc.connector.entity.living.merchant.VillagerEntity;
|
import com.nukkitx.protocol.bedrock.data.InventorySource;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.Translators;
|
|
||||||
import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
|
import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
|
||||||
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
|
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
|
||||||
|
|
||||||
|
@ -80,6 +73,14 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
|
||||||
return super.bedrockSlotToJava(action);
|
return super.bedrockSlotToJava(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlotType getSlotType(int javaSlot) {
|
||||||
|
if (javaSlot == 2) {
|
||||||
|
return SlotType.OUTPUT;
|
||||||
|
}
|
||||||
|
return SlotType.NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||||
|
|
||||||
|
@ -93,8 +94,6 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
|
||||||
@Override
|
@Override
|
||||||
public void closeInventory(GeyserSession session, Inventory inventory) {
|
public void closeInventory(GeyserSession session, Inventory inventory) {
|
||||||
session.setLastInteractedVillagerEid(-1);
|
session.setLastInteractedVillagerEid(-1);
|
||||||
session.setFirstTradeSlot(null);
|
|
||||||
session.setSecondTradeSlot(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -109,60 +108,10 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translateActions(GeyserSession session, Inventory inventory, List<InventoryActionData> actions) {
|
public void translateActions(GeyserSession session, Inventory inventory, List<InventoryActionData> actions) {
|
||||||
InventoryActionData result = null;
|
for (InventoryActionData action : actions) {
|
||||||
|
if (action.getSource().getType() == InventorySource.Type.NON_IMPLEMENTED_TODO) {
|
||||||
VillagerEntity villager = (VillagerEntity) session.getEntityCache().getEntityByGeyserId(session.getLastInteractedVillagerEid());
|
return;
|
||||||
if (villager == null) {
|
|
||||||
session.getConnector().getLogger().debug("Could not find villager with entity id: " + session.getLastInteractedVillagerEid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to store the trade slot data in the session itself as data
|
|
||||||
// needs to persist beyond this translateActions method since the client
|
|
||||||
// sends multiple packets for this
|
|
||||||
for (InventoryActionData data : actions) {
|
|
||||||
if (data.getSlot() == 4 && session.getFirstTradeSlot() == null && data.getSource().getContainerId() == ContainerId.CURSOR) {
|
|
||||||
session.setFirstTradeSlot(Translators.getItemTranslator().translateToJava(session, data.getToItem()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.getSlot() == 5 && session.getSecondTradeSlot() == null && data.getToItem() != null && data.getSource().getContainerId() == ContainerId.CURSOR) {
|
|
||||||
session.setSecondTradeSlot(Translators.getItemTranslator().translateToJava(session, data.getToItem()));
|
|
||||||
}
|
|
||||||
if (data.getSlot() == 50 && result == null) {
|
|
||||||
result = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == null || session.getFirstTradeSlot() == null) {
|
|
||||||
super.translateActions(session, inventory, actions);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack resultSlot = Translators.getItemTranslator().translateToJava(session, result.getToItem());
|
|
||||||
for (int i = 0; i < villager.getVillagerTrades().length; i++) {
|
|
||||||
VillagerTrade trade = villager.getVillagerTrades()[i];
|
|
||||||
if (!Translators.getItemTranslator().equals(session.getFirstTradeSlot(), trade.getFirstInput(), true, true, false) || !Translators.getItemTranslator().equals(resultSlot, trade.getOutput(), true, false, false)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session.getSecondTradeSlot() != null && trade.getSecondInput() != null && !Translators.getItemTranslator().equals(session.getSecondTradeSlot(), trade.getSecondInput(), true, false, false)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientSelectTradePacket selectTradePacket = new ClientSelectTradePacket(i);
|
|
||||||
session.sendDownstreamPacket(selectTradePacket);
|
|
||||||
|
|
||||||
ClientWindowActionPacket tradeAction = new ClientWindowActionPacket(
|
|
||||||
inventory.getId(),
|
|
||||||
inventory.getTransactionId().getAndIncrement(),
|
|
||||||
this.bedrockSlotToJava(result),
|
|
||||||
null,
|
|
||||||
WindowAction.CLICK_ITEM,
|
|
||||||
ClickItemParam.LEFT_CLICK
|
|
||||||
);
|
|
||||||
session.sendDownstreamPacket(tradeAction);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.translateActions(session, inventory, actions);
|
super.translateActions(session, inventory, actions);
|
||||||
|
|
|
@ -56,12 +56,13 @@ public class JavaTradeListTranslator extends PacketTranslator<ServerTradeListPac
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
villager.setVillagerTrades(packet.getTrades());
|
villager.setVillagerTrades(packet.getTrades());
|
||||||
villager.getMetadata().put(EntityData.TRADE_XP, packet.getExperience());
|
|
||||||
villager.getMetadata().put(EntityData.TRADE_TIER, packet.getVillagerLevel() - 1);
|
villager.getMetadata().put(EntityData.TRADE_TIER, packet.getVillagerLevel() - 1);
|
||||||
|
villager.getMetadata().put(EntityData.MAX_TRADE_TIER, 4);
|
||||||
|
villager.getMetadata().put(EntityData.TRADE_XP, packet.getExperience());
|
||||||
villager.updateBedrockMetadata(session);
|
villager.updateBedrockMetadata(session);
|
||||||
|
|
||||||
UpdateTradePacket updateTradePacket = new UpdateTradePacket();
|
UpdateTradePacket updateTradePacket = new UpdateTradePacket();
|
||||||
updateTradePacket.setTradeTier(packet.getVillagerLevel() + 1);
|
updateTradePacket.setTradeTier(packet.getVillagerLevel() - 1);
|
||||||
updateTradePacket.setWindowId((short) packet.getWindowId());
|
updateTradePacket.setWindowId((short) packet.getWindowId());
|
||||||
updateTradePacket.setWindowType((short) ContainerType.TRADING.id());
|
updateTradePacket.setWindowType((short) ContainerType.TRADING.id());
|
||||||
updateTradePacket.setDisplayName("Villager");
|
updateTradePacket.setDisplayName("Villager");
|
||||||
|
@ -75,41 +76,62 @@ public class JavaTradeListTranslator extends PacketTranslator<ServerTradeListPac
|
||||||
for (VillagerTrade trade : packet.getTrades()) {
|
for (VillagerTrade trade : packet.getTrades()) {
|
||||||
CompoundTagBuilder recipe = CompoundTagBuilder.builder();
|
CompoundTagBuilder recipe = CompoundTagBuilder.builder();
|
||||||
recipe.intTag("maxUses", trade.getMaxUses());
|
recipe.intTag("maxUses", trade.getMaxUses());
|
||||||
recipe.intTag("traderExp", packet.getExperience());
|
recipe.intTag("traderExp", trade.getXp());
|
||||||
recipe.floatTag("priceMultiplierA", trade.getPriceMultiplier());
|
recipe.floatTag("priceMultiplierA", trade.getPriceMultiplier());
|
||||||
recipe.tag(getItemTag(session, trade.getOutput(), "sell"));
|
recipe.tag(getItemTag(session, trade.getOutput(), "sell", 0));
|
||||||
recipe.floatTag("priceMultiplierB", 0.0f);
|
recipe.floatTag("priceMultiplierB", 0.0f);
|
||||||
recipe.intTag("buyCountB", 0);
|
recipe.intTag("buyCountB", trade.getSecondInput() != null ? trade.getSecondInput().getAmount() : 0);
|
||||||
recipe.intTag("buyCountA", trade.getOutput().getAmount());
|
recipe.intTag("buyCountA", trade.getFirstInput().getAmount());
|
||||||
recipe.intTag("demand", trade.getDemand());
|
recipe.intTag("demand", trade.getDemand());
|
||||||
recipe.intTag("tier", packet.getVillagerLevel() - 1);
|
recipe.intTag("tier", packet.getVillagerLevel() - 1);
|
||||||
recipe.tag(getItemTag(session, trade.getFirstInput(), "buyA"));
|
recipe.tag(getItemTag(session, trade.getFirstInput(), "buyA", trade.getSpecialPrice()));
|
||||||
if (trade.getSecondInput() != null) {
|
if (trade.getSecondInput() != null) {
|
||||||
recipe.tag(getItemTag(session, trade.getSecondInput(), "buyB"));
|
recipe.tag(getItemTag(session, trade.getSecondInput(), "buyB", 0));
|
||||||
}
|
}
|
||||||
recipe.intTag("uses", trade.getNumUses());
|
recipe.intTag("uses", trade.getNumUses());
|
||||||
recipe.byteTag("rewardExp", (byte) trade.getXp());
|
recipe.byteTag("rewardExp", (byte) 1);
|
||||||
tags.add(recipe.buildRootTag());
|
tags.add(recipe.buildRootTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Hidden trade to fix visual experience bug
|
||||||
|
if (packet.getVillagerLevel() < 5) {
|
||||||
|
tags.add(CompoundTagBuilder.builder()
|
||||||
|
.intTag("maxUses", 0)
|
||||||
|
.intTag("traderExp", 0)
|
||||||
|
.floatTag("priceMultiplierA", 0.0f)
|
||||||
|
.floatTag("priceMultiplierB", 0.0f)
|
||||||
|
.intTag("buyCountB", 0)
|
||||||
|
.intTag("buyCountA", 0)
|
||||||
|
.intTag("demand", 0)
|
||||||
|
.intTag("tier", 5)
|
||||||
|
.intTag("uses", 0)
|
||||||
|
.byteTag("rewardExp", (byte) 0)
|
||||||
|
.buildRootTag());
|
||||||
|
}
|
||||||
|
|
||||||
builder.listTag("Recipes", CompoundTag.class, tags);
|
builder.listTag("Recipes", CompoundTag.class, tags);
|
||||||
List<CompoundTag> expTags = new ArrayList<>();
|
List<CompoundTag> expTags = new ArrayList<>();
|
||||||
expTags.add(CompoundTagBuilder.builder().intTag("0", 0).buildRootTag());
|
expTags.add(CompoundTagBuilder.builder().intTag("0", 0).buildRootTag());
|
||||||
expTags.add(CompoundTagBuilder.builder().intTag("1", 10).buildRootTag());
|
expTags.add(CompoundTagBuilder.builder().intTag("1", 11).buildRootTag());
|
||||||
expTags.add(CompoundTagBuilder.builder().intTag("2", 60).buildRootTag());
|
expTags.add(CompoundTagBuilder.builder().intTag("2", 71).buildRootTag());
|
||||||
expTags.add(CompoundTagBuilder.builder().intTag("3", 160).buildRootTag());
|
expTags.add(CompoundTagBuilder.builder().intTag("3", 151).buildRootTag());
|
||||||
expTags.add(CompoundTagBuilder.builder().intTag("4", 310).buildRootTag());
|
expTags.add(CompoundTagBuilder.builder().intTag("4", 251).buildRootTag());
|
||||||
builder.listTag("TierExpRequirements", CompoundTag.class, expTags);
|
builder.listTag("TierExpRequirements", CompoundTag.class, expTags);
|
||||||
updateTradePacket.setOffers(builder.buildRootTag());
|
updateTradePacket.setOffers(builder.buildRootTag());
|
||||||
session.sendUpstreamPacket(updateTradePacket);
|
session.sendUpstreamPacket(updateTradePacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundTag getItemTag(GeyserSession session, ItemStack stack, String name) {
|
private CompoundTag getItemTag(GeyserSession session, ItemStack stack, String name, int specialPrice) {
|
||||||
ItemData itemData = Translators.getItemTranslator().translateToBedrock(session, stack);
|
ItemData itemData = Translators.getItemTranslator().translateToBedrock(session, stack);
|
||||||
ItemEntry itemEntry = Translators.getItemTranslator().getItem(stack);
|
ItemEntry itemEntry = Translators.getItemTranslator().getItem(stack);
|
||||||
CompoundTagBuilder builder = CompoundTagBuilder.builder();
|
CompoundTagBuilder builder = CompoundTagBuilder.builder();
|
||||||
builder.byteTag("Count", (byte) itemData.getCount());
|
builder.byteTag("Count", (byte) (Math.max(itemData.getCount() + specialPrice, 1)));
|
||||||
builder.shortTag("Damage", itemData.getDamage());
|
builder.shortTag("Damage", itemData.getDamage());
|
||||||
builder.stringTag("Name", itemEntry.getJavaIdentifier());
|
builder.shortTag("id", (short) itemEntry.getBedrockId());
|
||||||
|
if (itemData.getTag() != null) {
|
||||||
|
CompoundTag tag = itemData.getTag().toBuilder().build("tag");
|
||||||
|
builder.tag(tag);
|
||||||
|
}
|
||||||
return builder.build(name);
|
return builder.build(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue