Skip to content

Commit

Permalink
Address requests
Browse files Browse the repository at this point in the history
  • Loading branch information
Camotoy committed Mar 8, 2021
1 parent d19bf07 commit da11cd2
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public void onEnable() {

if (isPre1_12) {
// Register events needed to send all recipes to the client
Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigot1_11CraftingListener(this, connector), this);
Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigot1_11CraftingListener(connector), this);
}

this.getCommand("geyser").setExecutor(new GeyserSpigotCommandExecutor(connector));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.network.translators.item.RecipeRegistry;
import org.geysermc.platform.spigot.GeyserSpigotPlugin;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.data.MappingData;
import us.myles.ViaVersion.api.protocol.Protocol;
Expand All @@ -70,14 +69,12 @@ public class GeyserSpigot1_11CraftingListener implements Listener {
* The list of all protocols from the client's version to 1.13.
*/
private final List<Pair<Integer, Protocol>> protocolList;
private final ProtocolVersion version;

public GeyserSpigot1_11CraftingListener(GeyserSpigotPlugin plugin, GeyserConnector connector) {
public GeyserSpigot1_11CraftingListener(GeyserConnector connector) {
this.connector = connector;
this.mappingData1_12to1_13 = ProtocolRegistry.getProtocol(Protocol1_13To1_12_2.class).getMappingData();
this.protocolList = ProtocolRegistry.getProtocolPath(MinecraftConstants.PROTOCOL_VERSION,
ProtocolVersion.v1_13.getVersion());
this.version = plugin.getServerProtocolVersion();
}

@EventHandler
Expand All @@ -101,13 +98,16 @@ public void sendServerRecipes(GeyserSession session) {

CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
craftingDataPacket.setCleanRecipes(true);

Iterator<Recipe> recipeIterator = Bukkit.getServer().recipeIterator();
while (recipeIterator.hasNext()) {
Recipe recipe = recipeIterator.next();

Pair<ItemStack, ItemData> outputs = translateToBedrock(session, recipe.getResult());
ItemStack javaOutput = outputs.getKey();
ItemData output = outputs.getValue();
if (output.getId() == 0) continue; // If items make air we don't want that

boolean isNotAllAir = false; // Check for all-air recipes
if (recipe instanceof ShapedRecipe) {
ShapedRecipe shapedRecipe = (ShapedRecipe) recipe;
Expand All @@ -119,15 +119,17 @@ public void sendServerRecipes(GeyserSession session) {
Pair<ItemStack, ItemData> result = translateToBedrock(session, shapedRecipe.getIngredientMap().get((char) ('a' + i)));
ingredients[i] = new Ingredient(new ItemStack[]{result.getKey()});
input[i] = result.getValue();
isNotAllAir = isNotAllAir || input[i].getId() != 0;
isNotAllAir |= input[i].getId() != 0;
}

if (!isNotAllAir) continue;
UUID uuid = UUID.randomUUID();
// Add recipe to our internal cache
ShapedRecipeData data = new ShapedRecipeData(shapedRecipe.getShape()[0].length(), shapedRecipe.getShape().length,
"", ingredients, javaOutput);
session.getCraftingRecipes().put(netId,
new com.github.steveice10.mc.protocol.data.game.recipe.Recipe(RecipeType.CRAFTING_SHAPED, uuid.toString(), data));

// Add recipe for Bedrock
craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
shapedRecipe.getShape()[0].length(), shapedRecipe.getShape().length, Arrays.asList(input),
Expand All @@ -136,18 +138,21 @@ public void sendServerRecipes(GeyserSession session) {
ShapelessRecipe shapelessRecipe = (ShapelessRecipe) recipe;
Ingredient[] ingredients = new Ingredient[shapelessRecipe.getIngredientList().size()];
ItemData[] input = new ItemData[shapelessRecipe.getIngredientList().size()];

for (int i = 0; i < input.length; i++) {
Pair<ItemStack, ItemData> result = translateToBedrock(session, shapelessRecipe.getIngredientList().get(i));
ingredients[i] = new Ingredient(new ItemStack[]{result.getKey()});
input[i] = result.getValue();
isNotAllAir = isNotAllAir || input[i].getId() != 0;
isNotAllAir |= input[i].getId() != 0;
}

if (!isNotAllAir) continue;
UUID uuid = UUID.randomUUID();
// Add recipe to our internal cache
ShapelessRecipeData data = new ShapelessRecipeData("", ingredients, javaOutput);
session.getCraftingRecipes().put(netId,
new com.github.steveice10.mc.protocol.data.game.recipe.Recipe(RecipeType.CRAFTING_SHAPELESS, uuid.toString(), data));

// Add recipe for Bedrock
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
Arrays.asList(input), Collections.singletonList(output), uuid, "crafting_table", 0, netId++));
Expand All @@ -163,10 +168,13 @@ private Pair<ItemStack, ItemData> translateToBedrock(GeyserSession session, org.
if (itemStack.getType().getId() == 0) {
return new Pair<>(null, ItemData.AIR);
}

int legacyId = (itemStack.getType().getId() << 4) | (itemStack.getData().getData() & 0xFFFF);

if (itemStack.getType().getId() == 355 && itemStack.getData().getData() == (byte) 0) { // Handle bed color since the server will always be pre-1.12
legacyId = (itemStack.getType().getId() << 4) | ((byte) 14 & 0xFFFF);
}

// old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16 and so on
int itemId;
if (mappingData1_12to1_13.getItemMappings().containsKey(legacyId)) {
Expand All @@ -189,6 +197,7 @@ private Pair<ItemStack, ItemData> translateToBedrock(GeyserSession session, org.
ItemData finalData = ItemTranslator.translateToBedrock(session, mcItemStack);
return new Pair<>(mcItemStack, finalData);
}

// Empty slot, most likely
return new Pair<>(null, ItemData.AIR);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
import org.geysermc.connector.entity.CommandBlockMinecartEntity;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.ItemFrameEntity;
import org.geysermc.connector.entity.living.merchant.AbstractMerchantEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.inventory.GeyserItemStack;
import org.geysermc.connector.network.session.GeyserSession;
Expand Down Expand Up @@ -87,10 +86,10 @@ public void translate(InventoryTransactionPacket packet, GeyserSession session)
if (worldAction.getSource().getType() == InventorySource.Type.WORLD_INTERACTION
&& worldAction.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) {
session.addInventoryTask(() -> {
if (session.getPlayerInventory().getHeldItemSlot() != containerAction.getSlot())
return;
if (session.getPlayerInventory().getItemInHand().isEmpty())
if (session.getPlayerInventory().getHeldItemSlot() != containerAction.getSlot() ||
session.getPlayerInventory().getItemInHand().isEmpty()) {
return;
}

boolean dropAll = worldAction.getToItem().getCount() > 1;
ClientPlayerActionPacket dropAllPacket = new ClientPlayerActionPacket(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
Vector3i position = session.getLastInteractionBlockPosition();
// shouldRefresh means that we should boot out the client on our side because their lectern GUI isn't updated yet
boolean shouldRefresh = !session.getConnector().getWorldManager().shouldExpectLecternHandled() && !session.getLecternCache().contains(position);

NbtMap blockEntityTag;
if (tag != null) {
int pagesSize = ((ListTag) tag.get("pages")).size();
Expand Down Expand Up @@ -132,6 +133,7 @@ public void updateSlot(GeyserSession session, Inventory inventory, int slot) {

blockEntityTag = lecternTag.putCompound("book", bookTag.build()).build();
}

// Even with serverside access to lecterns, we don't easily know which lectern this is, so we need to rebuild
// the block entity tag
lecternContainer.setBlockEntityTag(blockEntityTag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession se
return rejectRequest(request);
}
CraftResultsDeprecatedStackRequestActionData craftData = (CraftResultsDeprecatedStackRequestActionData) data;

// Get the patterns compound tag
List<NbtMap> newBlockEntityTag = craftData.getResultItems()[0].getTag().getList("Patterns", NbtType.COMPOUND);
// Get the pattern that the Bedrock client requests - the last pattern in the Patterns list
Expand All @@ -151,6 +152,7 @@ public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession se
}
CompoundTag blockEntityTag = inputCopy.getNbt().get("BlockEntityTag");
CompoundTag javaBannerPattern = BannerTranslator.getJavaBannerPattern(pattern);

if (blockEntityTag != null) {
ListTag patternsList = blockEntityTag.get("Patterns");
if (patternsList != null) {
Expand All @@ -165,6 +167,7 @@ public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession se
blockEntityTag.put(patternsList);
inputCopy.getNbt().put(blockEntityTag);
}

// Set the new item as the output
inventory.setItem(3, inputCopy, session);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public static void updateCraftingGrid(GeyserSession session, Inventory inventory

if (session.getGameMode() == GameMode.CREATIVE) {
slotPacket.setItem(UNUSUABLE_CRAFTING_SPACE_BLOCK);
}else{
} else {
slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(i).getItemStack()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession se
return rejectRequest(request);
}
CraftResultsDeprecatedStackRequestActionData craftData = (CraftResultsDeprecatedStackRequestActionData) data;

StonecutterContainer container = (StonecutterContainer) inventory;
// Get the ID of the item we are cutting
int id = inventory.getItem(0).getJavaId();
Expand All @@ -73,6 +74,7 @@ public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession se
if (results == null) {
return rejectRequest(request);
}

ItemStack javaOutput = ItemTranslator.translateToJava(craftData.getResultItems()[0]);
int button = results.indexOf(javaOutput.getId());
// If we've already pressed the button with this item, no need to press it again!
Expand All @@ -86,6 +88,7 @@ public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession se
inventory.setItem(1, GeyserItemStack.from(javaOutput), session);
}
}

return translateRequest(session, inventory, request);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,20 +163,23 @@ public void translate(ServerDeclareRecipesPacket packet, GeyserSession session)

Int2ObjectMap<IntList> stonecutterRecipeMap = new Int2ObjectOpenHashMap<>();
for (Int2ObjectMap.Entry<List<StoneCuttingRecipeData>> data : unsortedStonecutterData.int2ObjectEntrySet()) {
// Sort the list by each output item's Java identifier - this is how it's sorted on Java, and therefore
// We can get the correct order for button pressing
data.getValue().sort(Comparator.comparing((stoneCuttingRecipeData ->
// Sort the list by each output item's Java identifier - this is how it's sorted on Java, and therefore
// We can get the correct order for button pressing
ItemRegistry.getItem(stoneCuttingRecipeData.getResult()).getJavaIdentifier())));

// Now that it's sorted, let's translate these recipes
for (StoneCuttingRecipeData stoneCuttingData : data.getValue()) {
// As of 1.16.4, all stonecutter recipes have one ingredient option
ItemStack ingredient = stoneCuttingData.getIngredient().getOptions()[0];
ItemData input = ItemTranslator.translateToBedrock(session, ingredient);
ItemData output = ItemTranslator.translateToBedrock(session, stoneCuttingData.getResult());
UUID uuid = UUID.randomUUID();

// We need to register stonecutting recipes so they show up on Bedrock
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
Collections.singletonList(input), Collections.singletonList(output), uuid, "stonecutter", 0, netId++));

// Save the recipe list for reference when crafting
IntList outputs = stonecutterRecipeMap.get(ingredient.getId());
if (outputs == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,8 @@ private static void updateCraftingGrid(GeyserSession session, ServerSetSlotPacke
}
}

if (Arrays.equals(ingredients, mirroredIngredients)) {
continue;
} else if (!testShapedRecipe(mirroredIngredients, inventory, gridDimensions, firstRow, height, firstCol, width)) {
if (Arrays.equals(ingredients, mirroredIngredients) ||
!testShapedRecipe(mirroredIngredients, inventory, gridDimensions, firstRow, height, firstCol, width)) {
continue;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public void translate(ServerTradeListPacket packet, GeyserSession session) {
updateTradePacket.setUsingEconomyTrade(true);
updateTradePacket.setPlayerUniqueEntityId(session.getPlayerEntity().getGeyserId());
updateTradePacket.setTraderUniqueEntityId(villager.getGeyserId());

NbtMapBuilder builder = NbtMap.builder();
boolean addExtraTrade = packet.isRegularVillager() && packet.getVillagerLevel() < 5;
List<NbtMap> tags = new ArrayList<>(addExtraTrade ? packet.getTrades().length + 1 : packet.getTrades().length);
Expand Down Expand Up @@ -119,20 +120,23 @@ public void translate(ServerTradeListPacket packet, GeyserSession session) {
}

builder.putList("Recipes", NbtType.COMPOUND, tags);

List<NbtMap> expTags = new ArrayList<>(5);
expTags.add(NbtMap.builder().putInt("0", 0).build());
expTags.add(NbtMap.builder().putInt("1", 10).build());
expTags.add(NbtMap.builder().putInt("2", 70).build());
expTags.add(NbtMap.builder().putInt("3", 150).build());
expTags.add(NbtMap.builder().putInt("4", 250).build());
builder.putList("TierExpRequirements", NbtType.COMPOUND, expTags);

updateTradePacket.setOffers(builder.build());
session.sendUpstreamPacket(updateTradePacket);
}

private NbtMap getItemTag(GeyserSession session, ItemStack stack, int specialPrice) {
ItemData itemData = ItemTranslator.translateToBedrock(session, stack);
ItemEntry itemEntry = ItemRegistry.getItem(stack);

NbtMapBuilder builder = NbtMap.builder();
builder.putByte("Count", (byte) (Math.max(itemData.getCount() + specialPrice, 1)));
builder.putShort("Damage", itemData.getDamage());
Expand All @@ -141,12 +145,14 @@ private NbtMap getItemTag(GeyserSession session, ItemStack stack, int specialPri
NbtMap tag = itemData.getTag().toBuilder().build();
builder.put("tag", tag);
}

NbtMap blockTag = BlockTranslator.getBedrockBlockNbt(itemEntry.getJavaIdentifier());
if (blockTag != null) {
// This fixes certain blocks being unable to stack after grabbing one
builder.putCompound("Block", blockTag);
builder.putShort("Damage", (short) 0);
}

return builder.build();
}
}

0 comments on commit da11cd2

Please sign in to comment.