Updated to add Fabric support. Advertises the fabric:registry/sync pl… - #286
Updated to add Fabric support. Advertises the fabric:registry/sync pl…#286Chadhendrixs wants to merge 1 commit into
Conversation
…ugin channel on join, and on join handles modded items by ignoring them (Previously failed to find fishing rod after modded item)
fd7fa51 to
4234e82
Compare
|
Hi @Chadhendrixs thanks for your PR, can you give me a name/link of a mod (preferable open-source), where this issue happens, this would help me reviewing it |
|
Heya! The mod that was causing me issues was Backpacked by Mr.Crayfish after I got it connecting to Fabric servers. It would fail with the error below and disconnect, then it would discard the whole inventory after fixing that so it now only discards the modded item it can't parse. The items was in the "backpack slot" in the mod, I'm guessing that's what caused the error in the first place. |
MrKinau
left a comment
There was a problem hiding this comment.
Hi again @Chadhendrixs
First of all, sorry for the delay, I wanted to review your PR earlier, but unfortunately wasn't able to.
Thanks for your PR this will definitely help connecting to fabric modded servers, thanks for taking your time looking into it.
The fabric registration payload and answering the sync packet is a great addition to spoof fabric. However the main issue with the mod mentioned at least is the fact it adds custom item components to the items it adds (e.g. backbacked:unlockable_slots to a backpack). As the single item payload length is no longer sent within the PacketInWindowItems (minecraft:container_set_content) we can't really know the contents of the bots inventory as we can't skip the items we can't read.
I've requested some changes only about allowing logging more exceptions and trying handling the modded components as NBTComponent, but overall your code looks good, I tested it and it works (at least for the mentioned mod and if there is no backback in an inventory slot before a rod, obviously).
Thanks again for your PR.
| } else if (!trySkipAsNbt(input, dataComponentType, protocolId)) { | ||
| // no way to know its length, rest of the slot is unneeded | ||
| FishingBot.getLog().severe("Invalid component: " + dataComponentType); | ||
| throw new IllegalStateException("Unknown data component type " + dataComponentType + ", cannot determine its payload length to skip it"); |
There was a problem hiding this comment.
Maybe not just try skipping the component, but if it can be read as NBT, just handle it as a NBTComponent with the correct component type id, that will also allow writing the item back later if necessary. Although this did not work for me for the components added by the backpack mod, I'm sure many modded components are just NBT due to lazyness converting legacy nbt item data to the modern component format.
| } else if (!trySkipAsNbt(input, dataComponentType, protocolId)) { | |
| // no way to know its length, rest of the slot is unneeded | |
| FishingBot.getLog().severe("Invalid component: " + dataComponentType); | |
| throw new IllegalStateException("Unknown data component type " + dataComponentType + ", cannot determine its payload length to skip it"); | |
| } else { | |
| try { | |
| NBTComponent nbtComponent = new NBTComponent(dataComponentType); | |
| int before = input.getAvailable(); | |
| nbtComponent.read(input, protocolId); | |
| int consumed = before - input.getAvailable(); | |
| FishingBot.getLog().warning("Unknown component " + dataComponentType + ": heuristically handled as NBT (" + consumed + " byte(s))"); | |
| presentComponents.add(nbtComponent); | |
| } catch (Exception e) { | |
| // no way to know its length, rest of the slot is unneeded | |
| FishingBot.getLog().severe("Invalid component: " + dataComponentType); | |
| throw new IllegalStateException("Unknown data component type " + dataComponentType + ", cannot determine its payload length to skip it"); | |
| } |
| // Best effort for unknown (modded) components: usually just plain NBT data, better compatability with modded items in inventory | ||
| private static boolean trySkipAsNbt(ByteArrayDataInputWrapper input, int dataComponentType, int protocolId) { | ||
| try { | ||
| int before = input.getAvailable(); | ||
| readNBT(input, protocolId); | ||
| int consumed = before - input.getAvailable(); | ||
| FishingBot.getLog().warning("Unknown component " + dataComponentType + ": heuristically skipped as NBT (" + consumed + " byte(s))"); | ||
| return true; | ||
| } catch (Exception e) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
see other change request within Packet
| // Best effort for unknown (modded) components: usually just plain NBT data, better compatability with modded items in inventory | |
| private static boolean trySkipAsNbt(ByteArrayDataInputWrapper input, int dataComponentType, int protocolId) { | |
| try { | |
| int before = input.getAvailable(); | |
| readNBT(input, protocolId); | |
| int consumed = before - input.getAvailable(); | |
| FishingBot.getLog().warning("Unknown component " + dataComponentType + ": heuristically skipped as NBT (" + consumed + " byte(s))"); | |
| return true; | |
| } catch (Exception e) { | |
| return false; | |
| } | |
| } |
| this.slots.add(readSlot(in, protocolId, networkHandler.getDataComponentRegistry())); | ||
| } catch (Exception e) { | ||
| // Keep the slots read so far instead of tossing the whole snapshot | ||
| FishingBot.getLog().warning("Could not read slot " + i + "/" + count + " of PacketInWindowItems (window " + windowId + "): " + e); |
There was a problem hiding this comment.
Tbh I'm not sure if it is a good idea to let this packet pass, as the inventory is not complete and may contain wrong items, but there might be the chance a fishing rod be read before the modded items which can't be read, thus allowing the automatic rod detection work. The bot not having full and/or incorrect inventory data may not be more of an issue than having no inventory data at all.
The only issue I see is that there is no way of logging the full exception, in case of an actual issue within reading items. I think it would be good to print the full exception when FishingBot.getInstance().getConfig().isLogItemData() is enabled
| FishingBot.getLog().warning("Could not read slot " + i + "/" + count + " of PacketInWindowItems (window " + windowId + "): " + e); | |
| FishingBot.getLog().warning("Could not read slot " + i + "/" + count + " of PacketInWindowItems (window " + windowId + "): " + e); | |
| if (FishingBot.getInstance().getConfig().isLogItemData()) | |
| e.printStackTrace(); |
Updated to add Fabric support. Advertises the fabric:registry/sync plugin channel on join, and on join handles modded items by ignoring them (Previously failed to find fishing rod after modded item)