Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 16:12:46 +01:00
Enchantment table works; anvil is almost there
Dieser Commit ist enthalten in:
Ursprung
009905184e
Commit
f4f804e1ca
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.inventory;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.window.WindowType;
|
||||
|
||||
public class AnvilContainer extends Container {
|
||||
public AnvilContainer(String title, int id, WindowType windowType, int size, PlayerInventory playerInventory) {
|
||||
super(title, id, windowType, size, playerInventory);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.inventory;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.window.WindowType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.EnchantOptionData;
|
||||
import lombok.Getter;
|
||||
|
||||
public class EnchantingContainer extends Container {
|
||||
/**
|
||||
* A cache of what Bedrock sees
|
||||
*/
|
||||
@Getter
|
||||
private final EnchantOptionData[] enchantOptions;
|
||||
/**
|
||||
* A mutable cache of what the server sends us
|
||||
*/
|
||||
@Getter
|
||||
private final GeyserEnchantOption[] geyserEnchantOptions;
|
||||
|
||||
public EnchantingContainer(String title, int id, WindowType windowType, int size, PlayerInventory playerInventory) {
|
||||
super(title, id, windowType, size, playerInventory);
|
||||
|
||||
enchantOptions = new EnchantOptionData[3];
|
||||
geyserEnchantOptions = new GeyserEnchantOption[3];
|
||||
for (int i = 0; i < geyserEnchantOptions.length; i++) {
|
||||
geyserEnchantOptions[i] = new GeyserEnchantOption(i);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.inventory;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.window.WindowType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.EnchantOptionData;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class EnchantmentInventory extends Inventory {
|
||||
private EnchantOptionData[] enchantOptions;
|
||||
|
||||
public EnchantmentInventory(String title, int id, WindowType windowType, int size) {
|
||||
super(title, id, windowType, size);
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.data.game.window.WindowType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
//TODO: Figure out what this is and if we should remove it
|
||||
@Getter
|
||||
public class FurnaceInventory extends Inventory {
|
||||
@Setter
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.inventory;
|
||||
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.EnchantData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.EnchantOptionData;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A mutable "wrapper" around {@link EnchantOptionData}
|
||||
*/
|
||||
@Setter
|
||||
public class GeyserEnchantOption {
|
||||
private static final List<EnchantData> EMPTY = Collections.emptyList();
|
||||
/**
|
||||
* This: https://cdn.discordapp.com/attachments/613168850925649981/791030657169227816/unknown.png
|
||||
* is controlled by the server.
|
||||
* So, of course, we have to throw in some easter eggs. ;)
|
||||
*/
|
||||
private static final List<String> ENCHANT_NAMES = Arrays.asList("tougher armor", "lukeeey", "fall better",
|
||||
"explode less", "camo toy", "breathe better", "rtm five one six", "armor stab", "water walk", "you are elsa",
|
||||
"tim two zero three", "fast walk nether", "oof ouch owie", "enemy on fire", "spider sad", "aj ferguson", "redned",
|
||||
"more items thx", "long sword reach", "fast tool", "give me block", "less breaky break", "cube craft",
|
||||
"strong arrow", "fist arrow", "spicy arrow", "many many arrows", "geyser", "come here fish", "i like this",
|
||||
"stabby stab", "supreme mortal", "avatar i guess", "more arrows", "fly finder seventeen", "in and out",
|
||||
"xp heals tools", "dragon proxy waz here");
|
||||
|
||||
@Getter
|
||||
private final int javaIndex;
|
||||
|
||||
private int xpCost = 0;
|
||||
private int javaEnchantIndex = -1;
|
||||
private int bedrockEnchantIndex = -1;
|
||||
private int enchantLevel = -1;
|
||||
|
||||
public GeyserEnchantOption(int javaIndex) {
|
||||
this.javaIndex = javaIndex;
|
||||
}
|
||||
|
||||
public EnchantOptionData build(GeyserSession session) {
|
||||
if (enchantLevel == -1) {
|
||||
// Should not be sent to the client, as it is supposed to be empty
|
||||
return null;
|
||||
}
|
||||
return new EnchantOptionData(xpCost, javaIndex + 16, EMPTY,
|
||||
Collections.singletonList(new EnchantData(bedrockEnchantIndex, enchantLevel)), EMPTY,
|
||||
javaEnchantIndex == -1 ? "unknown" : ENCHANT_NAMES.get(javaEnchantIndex), session.getItemNetId().incrementAndGet());
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.network.translators.bedrock;
|
||||
|
||||
import com.nukkitx.protocol.bedrock.packet.FilterTextPacket;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
|
||||
/**
|
||||
* Used to send strings to the client and filter out unwanted words.
|
||||
* Java doesn't care, so we don't care, and we approve all strings.
|
||||
*/
|
||||
@Translator(packet = FilterTextPacket.class)
|
||||
public class BedrockFilterTextTranslator extends PacketTranslator<FilterTextPacket> {
|
||||
|
||||
@Override
|
||||
public void translate(FilterTextPacket packet, GeyserSession session) {
|
||||
// TODO: Bedrock doesn't send this. Why?
|
||||
System.out.println(packet.toString());
|
||||
packet.setFromServer(true);
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
}
|
@ -62,29 +62,36 @@ public abstract class InventoryTranslator {
|
||||
|
||||
public static final Map<WindowType, InventoryTranslator> INVENTORY_TRANSLATORS = new HashMap<WindowType, InventoryTranslator>() {
|
||||
{
|
||||
/* Player Inventory */
|
||||
put(null, new PlayerInventoryTranslator()); //player inventory
|
||||
|
||||
/* Chest UIs */
|
||||
put(WindowType.GENERIC_9X1, new SingleChestInventoryTranslator(9));
|
||||
put(WindowType.GENERIC_9X2, new SingleChestInventoryTranslator(18));
|
||||
put(WindowType.GENERIC_9X3, new SingleChestInventoryTranslator(27));
|
||||
put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(36));
|
||||
put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(45));
|
||||
put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54));
|
||||
put(WindowType.CRAFTING, new CraftingInventoryTranslator());
|
||||
put(WindowType.SHULKER_BOX, new ShulkerInventoryTranslator());
|
||||
put(WindowType.BREWING_STAND, new BrewingInventoryTranslator());
|
||||
//put(WindowType.ANVIL, new AnvilInventoryTranslator());
|
||||
put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator());
|
||||
put(WindowType.MERCHANT, new MerchantInventoryTranslator());
|
||||
put(WindowType.SMITHING, new SmithingInventoryTranslator());
|
||||
//put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO
|
||||
|
||||
/* Furnaces */
|
||||
put(WindowType.FURNACE, new FurnaceInventoryTranslator());
|
||||
put(WindowType.BLAST_FURNACE, new BlastFurnaceInventoryTranslator());
|
||||
put(WindowType.SMOKER, new SmokerInventoryTranslator());
|
||||
|
||||
/* Specific Inventories */
|
||||
put(WindowType.ANVIL, new AnvilInventoryTranslator());
|
||||
put(WindowType.BREWING_STAND, new BrewingInventoryTranslator());
|
||||
put(WindowType.CRAFTING, new CraftingInventoryTranslator());
|
||||
put(WindowType.ENCHANTMENT, new EnchantingInventoryTranslator());
|
||||
put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator());
|
||||
put(WindowType.MERCHANT, new MerchantInventoryTranslator());
|
||||
put(WindowType.SHULKER_BOX, new ShulkerInventoryTranslator());
|
||||
put(WindowType.SMITHING, new SmithingInventoryTranslator());
|
||||
|
||||
/* Generics */
|
||||
put(WindowType.GENERIC_3X3, new GenericBlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER));
|
||||
put(WindowType.HOPPER, new GenericBlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER));
|
||||
//put(WindowType.BEACON, new AbstractBlockInventoryTranslator(1, "minecraft:beacon", ContainerType.BEACON)); //TODO*/
|
||||
//put(WindowType.BEACON, new AbstractBlockInventoryTranslator(1, "minecraft:beacon", ContainerType.BEACON)); //TODO
|
||||
|
||||
//put(WindowType.CARTOGRAPHY
|
||||
//put(WindowType.STONECUTTER
|
||||
@ -110,12 +117,30 @@ public abstract class InventoryTranslator {
|
||||
public abstract SlotType getSlotType(int javaSlot);
|
||||
public abstract Inventory createInventory(String name, int windowId, WindowType windowType, PlayerInventory playerInventory);
|
||||
|
||||
/**
|
||||
* Should be overrided if this request matches a certain criteria and shouldn't be treated normally.
|
||||
* E.G. anvil renaming or enchanting
|
||||
*/
|
||||
public boolean shouldHandleRequestFirst(StackRequestActionData action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@link #shouldHandleRequestFirst(StackRequestActionData)} returns true, this will be called
|
||||
*/
|
||||
public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequestPacket.Request request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void translateRequests(GeyserSession session, Inventory inventory, List<ItemStackRequestPacket.Request> requests) {
|
||||
ItemStackResponsePacket responsePacket = new ItemStackResponsePacket();
|
||||
for (ItemStackRequestPacket.Request request : requests) {
|
||||
if (request.getActions().length > 0) {
|
||||
StackRequestActionData firstAction = request.getActions()[0];
|
||||
if (firstAction.getType() == StackRequestActionType.CRAFT_RECIPE || firstAction.getType() == StackRequestActionType.CRAFT_RECIPE_AUTO) {
|
||||
if (shouldHandleRequestFirst(firstAction)) {
|
||||
// Some special request that shouldn't be processed normally
|
||||
responsePacket.getEntries().add(translateSpecialRequest(session, inventory, request));
|
||||
} else if (firstAction.getType() == StackRequestActionType.CRAFT_RECIPE || firstAction.getType() == StackRequestActionType.CRAFT_RECIPE_AUTO) {
|
||||
responsePacket.getEntries().add(translateCraftingRequest(session, inventory, request));
|
||||
} else if (firstAction.getType() == StackRequestActionType.CRAFT_CREATIVE) {
|
||||
// This is also used for pulling items out of creative
|
||||
@ -335,6 +360,23 @@ public abstract class InventoryTranslator {
|
||||
return rejectRequest(request);
|
||||
|
||||
if (isCursor(dropAction.getSource())) { //clicking outside of window
|
||||
if (session.getGameMode() == GameMode.CREATIVE && inventory instanceof PlayerInventory) {
|
||||
GeyserItemStack cursorItem = session.getPlayerInventory().getCursor();
|
||||
GeyserItemStack droppingItem = cursorItem.copy();
|
||||
// Subtract the cursor item by however much is being dropped
|
||||
cursorItem.setAmount(cursorItem.getAmount() - dropAction.getCount());
|
||||
if (cursorItem.isEmpty()) {
|
||||
// Cursor item no longer exists
|
||||
session.getPlayerInventory().setCursor(GeyserItemStack.EMPTY);
|
||||
}
|
||||
droppingItem.setAmount(dropAction.getCount());
|
||||
ClientCreativeInventoryActionPacket packet = new ClientCreativeInventoryActionPacket(
|
||||
Click.OUTSIDE_SLOT,
|
||||
droppingItem.getItemStack()
|
||||
);
|
||||
System.out.println(packet.toString());
|
||||
session.sendDownstreamPacket(packet);
|
||||
} else {
|
||||
int sourceAmount = plan.getCursor().getAmount();
|
||||
if (dropAction.getCount() == sourceAmount) { //drop all
|
||||
plan.add(Click.LEFT_OUTSIDE, Click.OUTSIDE_SLOT);
|
||||
@ -343,6 +385,7 @@ public abstract class InventoryTranslator {
|
||||
plan.add(Click.RIGHT_OUTSIDE, Click.OUTSIDE_SLOT); //drop one until goal is met
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { //dropping from inventory
|
||||
int sourceSlot = bedrockSlotToJava(dropAction.getSource());
|
||||
int sourceAmount = plan.getItem(sourceSlot).getAmount();
|
||||
@ -395,6 +438,10 @@ public abstract class InventoryTranslator {
|
||||
case CRAFT_RESULTS_DEPRECATED: {
|
||||
break;
|
||||
}
|
||||
case CRAFT_RECIPE_OPTIONAL: {
|
||||
// Anvils and cartography tables will handle this
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return rejectRequest(request);
|
||||
}
|
||||
@ -578,7 +625,14 @@ public abstract class InventoryTranslator {
|
||||
Collections.singletonList(makeItemEntry(session, 0, session.getPlayerInventory().getCursor())))));
|
||||
} else {
|
||||
int javaSlot = bedrockSlotToJava(transferAction.getDestination());
|
||||
GeyserItemStack existingItem = inventory.getItem(javaSlot);
|
||||
if (existingItem.getId() == javaCreativeItem.getId()) {
|
||||
// Adding more to an existing item
|
||||
existingItem.setAmount(existingItem.getAmount() + transferAction.getCount());
|
||||
javaCreativeItem = existingItem.getItemStack();
|
||||
} else {
|
||||
inventory.setItem(javaSlot, GeyserItemStack.from(javaCreativeItem, session.getItemNetId().getAndIncrement()));
|
||||
}
|
||||
ClientCreativeInventoryActionPacket creativeActionPacket = new ClientCreativeInventoryActionPacket(
|
||||
javaSlot,
|
||||
javaCreativeItem
|
||||
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.network.translators.inventory.translators;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.window.WindowType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
|
||||
import org.geysermc.connector.inventory.AnvilContainer;
|
||||
import org.geysermc.connector.inventory.Inventory;
|
||||
import org.geysermc.connector.inventory.PlayerInventory;
|
||||
import org.geysermc.connector.network.translators.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.connector.network.translators.inventory.updater.UIInventoryUpdater;
|
||||
|
||||
public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public AnvilInventoryTranslator() {
|
||||
super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) {
|
||||
if (slotInfoData.getContainer() == ContainerSlotType.ANVIL_INPUT) {
|
||||
return 0;
|
||||
}
|
||||
if (slotInfoData.getContainer() == ContainerSlotType.ANVIL_MATERIAL) {
|
||||
return 1;
|
||||
}
|
||||
if (slotInfoData.getContainer() == ContainerSlotType.ANVIL_RESULT || slotInfoData.getContainer() == ContainerSlotType.CREATIVE_OUTPUT) {
|
||||
return 2;
|
||||
}
|
||||
return super.bedrockSlotToJava(slotInfoData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BedrockContainerSlot javaSlotToBedrockContainer(int slot) {
|
||||
switch (slot) {
|
||||
case 0:
|
||||
return new BedrockContainerSlot(ContainerSlotType.ANVIL_INPUT, 1);
|
||||
case 1:
|
||||
return new BedrockContainerSlot(ContainerSlotType.ANVIL_MATERIAL, 2);
|
||||
case 2:
|
||||
return new BedrockContainerSlot(ContainerSlotType.ANVIL_RESULT, 50);
|
||||
}
|
||||
return super.javaSlotToBedrockContainer(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int javaSlotToBedrock(int slot) {
|
||||
switch (slot) {
|
||||
case 0:
|
||||
return 1;
|
||||
case 1:
|
||||
return 2;
|
||||
case 2:
|
||||
return 50;
|
||||
}
|
||||
return super.javaSlotToBedrock(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory createInventory(String name, int windowId, WindowType windowType, PlayerInventory playerInventory) {
|
||||
return new AnvilContainer(name, windowId, windowType, this.size, playerInventory);
|
||||
}
|
||||
}
|
@ -30,11 +30,11 @@ import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
|
||||
import org.geysermc.connector.network.translators.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.connector.network.translators.inventory.SlotType;
|
||||
import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
|
||||
import org.geysermc.connector.network.translators.inventory.updater.UIInventoryUpdater;
|
||||
|
||||
public class CraftingInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public CraftingInventoryTranslator() {
|
||||
super(10, "minecraft:crafting_table", ContainerType.WORKBENCH, CursorInventoryUpdater.INSTANCE);
|
||||
super(10, "minecraft:crafting_table", ContainerType.WORKBENCH, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,11 +25,195 @@
|
||||
|
||||
package org.geysermc.connector.network.translators.inventory.translators;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.window.WindowType;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientClickWindowButtonPacket;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.EnchantOptionData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.CraftRecipeStackRequestActionData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType;
|
||||
import com.nukkitx.protocol.bedrock.packet.ItemStackRequestPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlayerEnchantOptionsPacket;
|
||||
import org.geysermc.connector.inventory.EnchantingContainer;
|
||||
import org.geysermc.connector.inventory.Inventory;
|
||||
import org.geysermc.connector.inventory.PlayerInventory;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.connector.network.translators.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.connector.network.translators.item.Enchantment;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
public class EnchantingInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public EnchantingInventoryTranslator() {
|
||||
super(2, "minecraft:enchanting_table", ContainerType.ENCHANTMENT, CursorInventoryUpdater.INSTANCE);
|
||||
super(2, "minecraft:enchanting_table", ContainerType.ENCHANTMENT, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) {
|
||||
int slotToUpdate;
|
||||
EnchantingContainer enchantingInventory = (EnchantingContainer) inventory;
|
||||
boolean shouldUpdate = false;
|
||||
switch (key) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
// Experience required
|
||||
slotToUpdate = key;
|
||||
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setXpCost(value);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
// Enchantment type
|
||||
slotToUpdate = key - 4;
|
||||
int index = value;
|
||||
if (index != -1) {
|
||||
Enchantment enchantment = Enchantment.getByJavaIdentifier("minecraft:" + JavaEnchantment.values()[index].name().toLowerCase());
|
||||
if (enchantment != null) {
|
||||
// Convert the Java enchantment index to Bedrock's
|
||||
index = enchantment.ordinal();
|
||||
} else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setJavaEnchantIndex(value);
|
||||
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setBedrockEnchantIndex(index);
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
// Enchantment level
|
||||
slotToUpdate = key - 7;
|
||||
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setEnchantLevel(value);
|
||||
shouldUpdate = true; // Java sends each property as its own packet, so let's only update after all properties have been sent
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (shouldUpdate) {
|
||||
enchantingInventory.getEnchantOptions()[slotToUpdate] = enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].build(session);
|
||||
PlayerEnchantOptionsPacket packet = new PlayerEnchantOptionsPacket();
|
||||
packet.getOptions().addAll(Arrays.asList(enchantingInventory.getEnchantOptions()));
|
||||
System.out.println(packet);
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldHandleRequestFirst(StackRequestActionData action) {
|
||||
return action.getType() == StackRequestActionType.CRAFT_RECIPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequestPacket.Request request) {
|
||||
// Client has requested an item to be enchanted
|
||||
CraftRecipeStackRequestActionData craftRecipeData = (CraftRecipeStackRequestActionData) request.getActions()[0];
|
||||
EnchantingContainer enchantingInventory = (EnchantingContainer) inventory;
|
||||
int javaSlot = -1;
|
||||
for (int i = 0; i < enchantingInventory.getEnchantOptions().length; i++) {
|
||||
EnchantOptionData enchantData = enchantingInventory.getEnchantOptions()[i];
|
||||
if (enchantData != null) {
|
||||
if (craftRecipeData.getRecipeNetworkId() == enchantData.getEnchantNetId()) {
|
||||
// Enchant net ID is how we differentiate between what item Bedrock wants
|
||||
javaSlot = enchantingInventory.getGeyserEnchantOptions()[i].getJavaIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (javaSlot == -1) {
|
||||
// Slot should be determined as 0, 1, or 2
|
||||
throw new RuntimeException("Cannot find enchant slot for item!");
|
||||
}
|
||||
ClientClickWindowButtonPacket packet = new ClientClickWindowButtonPacket(inventory.getId(), javaSlot);
|
||||
System.out.println(packet);
|
||||
session.sendDownstreamPacket(packet);
|
||||
return acceptRequest(request, makeContainerEntries(session, inventory, Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) {
|
||||
if (slotInfoData.getContainer() == ContainerSlotType.ENCHANTING_INPUT) {
|
||||
return 0;
|
||||
}
|
||||
if (slotInfoData.getContainer() == ContainerSlotType.ENCHANTING_LAPIS) {
|
||||
return 1;
|
||||
}
|
||||
return super.bedrockSlotToJava(slotInfoData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BedrockContainerSlot javaSlotToBedrockContainer(int slot) {
|
||||
if (slot == 0) {
|
||||
return new BedrockContainerSlot(ContainerSlotType.ENCHANTING_INPUT, 14);
|
||||
}
|
||||
if (slot == 1) {
|
||||
return new BedrockContainerSlot(ContainerSlotType.ENCHANTING_LAPIS, 15);
|
||||
}
|
||||
return super.javaSlotToBedrockContainer(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int javaSlotToBedrock(int slot) {
|
||||
if (slot == 0) {
|
||||
return 14;
|
||||
}
|
||||
if (slot == 1) {
|
||||
return 15;
|
||||
}
|
||||
return super.javaSlotToBedrock(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory createInventory(String name, int windowId, WindowType windowType, PlayerInventory playerInventory) {
|
||||
return new EnchantingContainer(name, windowId, windowType, this.size, playerInventory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enchantments classified by their Java index
|
||||
*/
|
||||
public enum JavaEnchantment {
|
||||
PROTECTION,
|
||||
FIRE_PROTECTION,
|
||||
FEATHER_FALLING,
|
||||
BLAST_PROTECTION,
|
||||
PROJECTILE_PROTECTION,
|
||||
RESPIRATION,
|
||||
AQUA_AFFINITY,
|
||||
THORNS,
|
||||
DEPTH_STRIDER,
|
||||
FROST_WALKER,
|
||||
BINDING_CURSE,
|
||||
SOUL_SPEED,
|
||||
SHARPNESS,
|
||||
SMITE,
|
||||
BANE_OF_ARTHROPODS,
|
||||
KNOCKBACK,
|
||||
FIRE_ASPECT,
|
||||
LOOTING,
|
||||
SWEEPING,
|
||||
EFFICIENCY,
|
||||
SILK_TOUCH,
|
||||
UNBREAKING,
|
||||
FORTUNE,
|
||||
POWER,
|
||||
PUNCH,
|
||||
FLAME,
|
||||
INFINITY,
|
||||
LUCK_OF_THE_SEA,
|
||||
LURE,
|
||||
LOYALTY,
|
||||
IMPALING,
|
||||
RIPTIDE,
|
||||
CHANNELING,
|
||||
MULTISHOT,
|
||||
QUICK_CHARGE,
|
||||
PIERCING,
|
||||
MENDING,
|
||||
VANISHING_CURSE
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,11 @@ import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
|
||||
import org.geysermc.connector.network.translators.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
|
||||
import org.geysermc.connector.network.translators.inventory.updater.UIInventoryUpdater;
|
||||
|
||||
public class GrindstoneInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public GrindstoneInventoryTranslator() {
|
||||
super(3, "minecraft:grindstone[face=floor,facing=north]", ContainerType.GRINDSTONE, CursorInventoryUpdater.INSTANCE);
|
||||
super(3, "minecraft:grindstone[face=floor,facing=north]", ContainerType.GRINDSTONE, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,12 +44,11 @@ import org.geysermc.connector.network.translators.inventory.updater.InventoryUpd
|
||||
import org.geysermc.connector.network.translators.inventory.updater.UIInventoryUpdater;
|
||||
|
||||
public class MerchantInventoryTranslator extends BaseInventoryTranslator {
|
||||
|
||||
private final InventoryUpdater updater;
|
||||
|
||||
public MerchantInventoryTranslator() {
|
||||
super(3);
|
||||
this.updater = new UIInventoryUpdater();
|
||||
this.updater = UIInventoryUpdater.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,11 +29,11 @@ import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
|
||||
import org.geysermc.connector.network.translators.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
|
||||
import org.geysermc.connector.network.translators.inventory.updater.UIInventoryUpdater;
|
||||
|
||||
public class SmithingInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public SmithingInventoryTranslator() {
|
||||
super(3, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, CursorInventoryUpdater.INSTANCE);
|
||||
super(3, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.network.translators.inventory.updater;
|
||||
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
|
||||
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
||||
import org.geysermc.connector.inventory.Inventory;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||
|
||||
public class CursorInventoryUpdater extends InventoryUpdater {
|
||||
public static final CursorInventoryUpdater INSTANCE = new CursorInventoryUpdater();
|
||||
|
||||
@Override
|
||||
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
super.updateInventory(translator, session, inventory);
|
||||
|
||||
for (int i = 0; i < translator.size; i++) {
|
||||
final int bedrockSlot = translator.javaSlotToBedrock(i);
|
||||
if (bedrockSlot == 50)
|
||||
continue;
|
||||
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||
slotPacket.setContainerId(ContainerId.UI);
|
||||
slotPacket.setSlot(bedrockSlot);
|
||||
slotPacket.setItem(inventory.getItem(i).getItemData(session));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
if (super.updateSlot(translator, session, inventory, javaSlot))
|
||||
return true;
|
||||
|
||||
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||
slotPacket.setContainerId(ContainerId.UI);
|
||||
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
|
||||
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -30,9 +30,9 @@ import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
||||
import org.geysermc.connector.inventory.Inventory;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||
|
||||
public class UIInventoryUpdater extends InventoryUpdater {
|
||||
public static final UIInventoryUpdater INSTANCE = new UIInventoryUpdater();
|
||||
|
||||
@Override
|
||||
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
|
@ -38,6 +38,7 @@ public class JavaWindowPropertyTranslator extends PacketTranslator<ServerWindowP
|
||||
|
||||
@Override
|
||||
public void translate(ServerWindowPropertyPacket packet, GeyserSession session) {
|
||||
System.out.println(packet.toString());
|
||||
session.addInventoryTask(() -> {
|
||||
Inventory inventory = InventoryUtils.getInventory(session, packet.getWindowId());
|
||||
if (inventory == null)
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren