Jump to content

Recommended Posts

Posted (edited)

I am currently working on a mod that requires me to know the LWGJL codes for keys on the keyboard. Luckily the Keyboard class has static fields that correspond to the keys of a QWERTY keyboard.  However, I am now trying to add international support and I cannot find an easy way to get codes for keys such as umlauts. I am currently doing it by printing the output of the getKeyCode() method in net.minecraft.client.settings.KeyBinding when a binding is changed in the controls gui, but this is impractical for anything more than a few codes. 

 

Does anyone know of an easier way to get these codes?

Edited by MrNerdy42
Posted

What are you trying to do?

Not "How do you intend to solve the problem" but  what is your goal?

 

From the end-user stand point what are you expecting? No code.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Well, it works doesnt it? I always say "If it aint broke dont fix it" unless there is a more efficient way of doing it. Code can sometimes be tedious but every time you think you are having a rough time, think of the people who had to map out google maps. That took ages.

Posted

Well your code is broken isn't it?

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Your solution is actually probably better than using hardcoded keycodes. Keys on different keyboard layouts can share keycodes despite actually being different characters (MC-7255). If you use the user input to tell you which keycode is what character, you will probably avoid some cross-layout problems.

Posted
  On 3/26/2017 at 8:02 PM, Draco18s said:

What are you trying to do?

Not "How do you intend to solve the problem" but  what is your goal?

 

From the end-user stand point what are you expecting? No code.

Expand  

I am drawing a keyboard on  the screen to help visualize and fix key conflicts. When you hover over the keys on the screen, text pops up to show you what they key is bound to. To accomplish this, I just iterate through a list of keybindings  and search for ones that match the key code.

 

  On 3/26/2017 at 10:25 PM, Draco18s said:

Well your code is broken isn't it?

Expand  

No, it's not broken. 

Posted
  On 3/27/2017 at 1:08 PM, MrNerdy42 said:

No, it's not broken. 

Expand  

Well it's clearly not working in the desired manner. Ergo, something's wrong.

 

Now that your use-case is clear, an approach can be made.  Unfortunately I'm not savvy enough with the aspects involved to offer any insight or alternatives.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
  On 3/27/2017 at 3:01 PM, Draco18s said:

Well it's clearly not working in the desired manner. Ergo, something's wrong.

 

Now that your use-case is clear, an approach can be made.  Unfortunately I'm not savvy enough with the aspects involved to offer any insight or alternatives.

Expand  

Thanks for the effort anyway.

Posted (edited)
  On 3/27/2017 at 3:38 PM, diesieben07 said:

Does Keyboard.getEventCharacter not do what you want?

Expand  

If I understand correctly getEventCharacter returns the character that was pressed such as 'a' if i pressed the A key. I am looking for  an easy way to find the numerical codes for international keys other then pressing each one by one and printing the result of KeyBinding .getKeyCode(). Right now, however, it looks like this in the only way.

Edited by MrNerdy42
Posted
  On 3/28/2017 at 8:50 PM, diesieben07 said:

Well... why? What do you need the key codes for?

Expand  

I probably should have added this to my original post, but here's the link to the mod I'm on the Minecraft Forums: http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-mods/2802980-1-10-2-keyboard-wizard-key-conflict-helper I use the codes to draw the keys on the screen, as well as change the current binding when the key is pressed.

Posted

I draw each key with a for loop that counts through the lwgjl ids:

for (int i=2; i<14; i++) {
		button = new GuiButton(this.currentId, (startX+rowPos*30), startY, 25, 20, translateKey(i));
		this.buttonList.add(button);
  		currentId++;
}

I use translateKey(int id), which is just a modified version of Keyboard.getKeyName(int id), to get the name of the key. The id is also used to with setKeyModifierAndCode

 

Posted

Plus, LWJGL doesn't support accented keys (had problems with the caron myself), so users shouldn't be able to assign those keys to keybinds in the first place. That key will either have a different keycode in LWJGL, ie. it will be mapped to something it supports, or it will fall back to the 0 - "dunno-what-this-is" keycode. If I remember correctly, minecraft keeps a keybind unchanged when one attempts to assign a 0 key to it.

Getting the layout of the current keyboard layout is very probably system-dependent and would require per-OS code along with either JNI or JNA.

Posted

I was able to  set a keybind to the umlauts on a QWERTZ keyboard, however this may be Minecraft's trickery not lwgjl. I guess I'll just have to dig deeper into the source to see what's going on there. 

Posted

Why would you need to iterate over hardware keys?

The best you can do, I think, is make a Map<Key, List<Keybind>> (Key being the identifier you use, int or whatever), initialize it for standard English keys on the keyboard (those that you are rendering in the current version, with empty lists), then add all KeyBinds you get from minecraft to this map, organized by the Key.

Afterwards, you iterate over the map's entries, and if you know where a key is (ie. it's a standard English one, like those that you are rendering already), you render it in the keyboard; and if you don't ie. it's a non-standard key, whatever it may be, you render it in an extra separated row below or above the keyboard, with its text being the one that you get from Minecraft in the way you are doing already, or you display the keycode as a raw value.

Not that I am stupid and there are probably better storage structures to use, but the general concept is fine I think.

Posted
  On 3/30/2017 at 7:27 PM, HashtagShell said:

Why would you need to iterate over hardware keys?

The best you can do, I think, is make a Map<Key, List<Keybind>> (Key being the identifier you use, int or whatever), initialize it for standard English keys on the keyboard (those that you are rendering in the current version, with empty lists), then add all KeyBinds you get from minecraft to this map, organized by the Key.

Afterwards, you iterate over the map's entries, and if you know where a key is (ie. it's a standard English one, like those that you are rendering already), you render it in the keyboard; and if you don't ie. it's a non-standard key, whatever it may be, you render it in an extra separated row below or above the keyboard, with its text being the one that you get from Minecraft in the way you are doing already, or you display the keycode as a raw value.

Not that I am stupid and there are probably better storage structures to use, but the general concept is fine I think.

Expand  

That's actually a great idea. This could also be a useful concept for sorting the unwieldy list of bindings on the left. The only flaw I can see is that the keys will not appear unless there is something already bound to it, which would require a trip to vanilla controls gui, but this is small. I think I will try to implement this as a sorting function first. Thanks a ton!

Posted

You can render the default english layout the way you are doing right now, iteratively, hardcoded-ly. they just won't have any actual keybinds attached to them. You could also use this further, rendering them a slightly darker shade of grey, making the important keys (assigned and/or conflicting) pop out.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

  Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

  Your link has been automatically embedded.   Display as a link instead

  Your previous content has been restored.   Clear editor

  You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Hi! I'm trying to add my custom models/textures renderer like this: public class PonyPlayerWrapperRenderer extends EntityRenderer<Player> { // wrapper class under my LivingEntityRenderer class implementation private final PonyPlayerRenderer innerRenderer; private final PonyPlayerRenderer innerSlimRenderer; public PonyPlayerWrapperRenderer(final EntityRendererProvider.Context context) { super(context); System.out.println("creating new PonyPlayerWrapperRenderer"); this.innerRenderer = new PonyPlayerRenderer(context, false); this.innerSlimRenderer = new PonyPlayerRenderer(context, true); } @Override public void render(final Player entity, final float yaw, final float partialTicks, final PoseStack poseStack, final MultiBufferSource bufferSource, final int packedLight) { System.out.println("PonyPlayerWrapperRenderer render: " + entity.toString()); if (entity instanceof AbstractClientPlayer clientPlayer) { if (clientPlayer.getModelName().contains("slim")) { innerSlimRenderer.render(clientPlayer, yaw, partialTicks, poseStack, bufferSource, packedLight); } else { innerRenderer.render(clientPlayer, yaw, partialTicks, poseStack, bufferSource, packedLight); } } } @Override public ResourceLocation getTextureLocation(final Player player) { System.out.println("PonyPlayerWrapperRenderer getTextureLocation"); if (player instanceof AbstractClientPlayer clientPlayer) { return clientPlayer.getSkinTextureLocation(); } System.out.println("player instanceof AbstractClientPlayer is false"); return getDefaultSkin(player.getUUID()); } } public class PonyPlayerRenderer extends LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> { private final PlayerModel<AbstractClientPlayer> earthModel; private final PlayerModel<AbstractClientPlayer> pegasusModel; private final PlayerModel<AbstractClientPlayer> unicornModel; public PonyPlayerRenderer(final EntityRendererProvider.Context context, final boolean slim) { super( context, slim ? new PonyModelSlim(context.bakeLayer(PonyModelSlim.LAYER_LOCATION)) : new PonyModel(context.bakeLayer(PonyModel.LAYER_LOCATION)), 0.5f ); System.out.println("creating new PonyPlayerRenderer"); this.earthModel = slim ? new PonyModelSlim(context.bakeLayer(PonyModelSlim.LAYER_LOCATION)) : new PonyModel(context.bakeLayer(PonyModel.LAYER_LOCATION)); this.pegasusModel = new PegasusModel(context.bakeLayer(PegasusModel.LAYER_LOCATION)); this.unicornModel = new UnicornModel(context.bakeLayer(UnicornModel.LAYER_LOCATION)); } @Override public void render(final AbstractClientPlayer player, final float entityYaw, final float partialTicks, final PoseStack poseStack, final MultiBufferSource buffer, final int packedLight) { final PonyRace race = player.getCapability(PONY_DATA) .map(data -> ofNullable(data.getRace()).orElse(PonyRace.EARTH)) .orElse(PonyRace.EARTH); this.model = switch (race) { case PEGASUS -> pegasusModel; case UNICORN -> unicornModel; case EARTH -> earthModel; }; super.render(player, entityYaw, partialTicks, poseStack, buffer, packedLight); } @Override public ResourceLocation getTextureLocation(final AbstractClientPlayer player) { final PonyRace race = player.getCapability(PONY_DATA) .map(data -> ofNullable(data.getRace()).orElse(PonyRace.EARTH)) .orElse(PonyRace.EARTH); return switch (race) { case EARTH -> fromNamespaceAndPath(MODID, "textures/entity/earth_pony.png"); case PEGASUS -> fromNamespaceAndPath(MODID, "textures/entity/pegasus.png"); case UNICORN -> fromNamespaceAndPath(MODID, "textures/entity/unicorn.png"); }; } } @Mod.EventBusSubscriber(modid = MODID, bus = MOD, value = CLIENT) public class ClientRenderers { // mod bus render registration config @SubscribeEvent public static void onRegisterLayerDefinitions(final EntityRenderersEvent.RegisterLayerDefinitions event) { event.registerLayerDefinition(PonyModel.LAYER_LOCATION, PonyModel::createBodyLayer); event.registerLayerDefinition(PonyModelSlim.LAYER_LOCATION, PonyModelSlim::createBodyLayer); event.registerLayerDefinition(PegasusModel.LAYER_LOCATION, PegasusModel::createBodyLayer); event.registerLayerDefinition(UnicornModel.LAYER_LOCATION, UnicornModel::createBodyLayer); event.registerLayerDefinition(InnerPonyArmorModel.LAYER_LOCATION, InnerPonyArmorModel::createBodyLayer); event.registerLayerDefinition(OuterPonyArmorModel.LAYER_LOCATION, OuterPonyArmorModel::createBodyLayer); } @SubscribeEvent public static void onRegisterRenderers(final EntityRenderersEvent.RegisterRenderers event) { event.registerEntityRenderer(EntityType.PLAYER, PonyPlayerWrapperRenderer::new); System.out.println("onRegisterRenderers end"); } } Method onRegisterRenderers() is called and I can see it being logged. But when I enter the world, my PonyWrapperRenderer render() method doesn't ever seem to be called. I also tried to put my renderer to EntityRenderDispatcher's playerRenderers via reflection: @Mod.EventBusSubscriber(modid = MODID, bus = MOD, value = CLIENT) public class ClientRenderers { @SubscribeEvent public static void onRegisterLayerDefinitions(final EntityRenderersEvent.RegisterLayerDefinitions event) { event.registerLayerDefinition(PonyModel.LAYER_LOCATION, PonyModel::createBodyLayer); event.registerLayerDefinition(PonyModelSlim.LAYER_LOCATION, PonyModelSlim::createBodyLayer); event.registerLayerDefinition(PegasusModel.LAYER_LOCATION, PegasusModel::createBodyLayer); event.registerLayerDefinition(UnicornModel.LAYER_LOCATION, UnicornModel::createBodyLayer); event.registerLayerDefinition(InnerPonyArmorModel.LAYER_LOCATION, InnerPonyArmorModel::createBodyLayer); event.registerLayerDefinition(OuterPonyArmorModel.LAYER_LOCATION, OuterPonyArmorModel::createBodyLayer); } @SubscribeEvent public static void onClientSetup(final FMLClientSetupEvent event) { event.enqueueWork(() -> { try { final EntityRenderDispatcher dispatcher = Minecraft.getInstance().getEntityRenderDispatcher(); final Field renderersField = getEntityRenderDispatcherField("playerRenderers"); final Field itemInHandRenderer = getEntityRenderDispatcherField("itemInHandRenderer"); @SuppressWarnings("unchecked") final Map<String, EntityRenderer<? extends Player>> playerRenderers = (Map<String, EntityRenderer<? extends Player>>)renderersField.get(dispatcher); final PonyPlayerWrapperRenderer renderer = new PonyPlayerWrapperRenderer( new EntityRendererProvider.Context( dispatcher, Minecraft.getInstance().getItemRenderer(), Minecraft.getInstance().getBlockRenderer(), (ItemInHandRenderer)itemInHandRenderer.get(dispatcher), Minecraft.getInstance().getResourceManager(), Minecraft.getInstance().getEntityModels(), Minecraft.getInstance().font ) ); playerRenderers.put("default", renderer); playerRenderers.put("slim", renderer); System.out.println("Player renderers replaced"); } catch (final Exception e) { throw new RuntimeException("Failed to replace player renderers", e); } }); } private static Field getEntityRenderDispatcherField(final String fieldName) throws NoSuchFieldException { final Field field = EntityRenderDispatcher.class.getDeclaredField(fieldName); field.setAccessible(true); return field; } } But I receive the error before Minecraft Client appears (RuntimeException: Failed to replace player renderers - from ClientRenderers onClientSetup() method - and its cause below): java.lang.IllegalArgumentException: No model for layer anotherlittlepony:earth_pony#main at net.minecraft.client.model.geom.EntityModelSet.bakeLayer(EntityModelSet.java:18) ~[forge-1.20.1-47.4.0_mapped_official_1.20.1-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.renderer.entity.EntityRendererProvider$Context.bakeLayer(EntityRendererProvider.java:69) ~[forge-1.20.1-47.4.0_mapped_official_1.20.1-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at com.thuggeelya.anotherlittlepony.client.renderer.pony.PonyPlayerRenderer.<init>(PonyPlayerRenderer.java:32) ~[main/:?] {re:classloading} at com.thuggeelya.anotherlittlepony.client.renderer.pony.PonyPlayerWrapperRenderer.<init>(PonyPlayerWrapperRenderer.java:24) ~[main/:?] {re:classloading} at com.thuggeelya.anotherlittlepony.client.renderer.ClientRenderers.lambda$onClientSetup$0(ClientRenderers.java:79) ~[main/:?] {re:classloading} ... 33 more Problem appears when EntityRendererProvider context tries to bakeLayer with my model layer location: new PonyModel(context.bakeLayer(PonyModel.LAYER_LOCATION)); // PonyPlayerRenderer.java:32 public class PonyModel extends PlayerModel<AbstractClientPlayer> { // the model class itself public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation( ResourceLocation.fromNamespaceAndPath(MODID, "earth_pony"), "main" ); public PonyModel(final ModelPart root) { super(root, false); } public static LayerDefinition createBodyLayer() { // some CubeListBuilder stuff for model appearance } } Textures PNGs are placed at: resources/assets/[my mod id]/textures/entity. My forge version is 1.20.1. Would appreciate any help.
    • Well, a bit more information about what you're trying to do would be helpful. e.g. why you're trying to use "INVOKE_ASSIGN" instead of "INVOKE". "INVOKE_ASSIGN" calls your code after the "target" is called and its value is stored, if applicable. "INVOKE" calls your code before the target is called. "target" expects a fully qualified name, as per the SpongePowered docs, if that name is going to be remapped (which it will be if your injecting into Minecraft itself and not another mod). For more information on fully qualified names versus canonical names, see the Java specifications. Here's an example of a working "@At" from my own code that targets the "getClosestsVulnerablePlayerToEntity" call inside a mob's logic: @At(value = "INVOKE_ASSIGN", target = "net.minecraft.world.World.getClosestVulnerablePlayerToEntity(Lnet/minecraft/entity/Entity;D)Lnet/minecraft/entity/player/EntityPlayer;") Hope this helps!
    • Ran it one more time just to check, and there's no errors this time on the log??? Log : https://mclo.gs/LnuaAiu I tried allocating more memory to the modpack, around 8000MB and it's still the same; stopping at "LOAD_REGISTRIES". Are some of the mods clashing, maybe? I have no clue what to do LOL
    • Tried removing some biome generation mods and test ran it again, but it's still the same; still not responding as soon as it gets to "LOAD_REGISTRIES". This time with more errors though. Log : https://mclo.gs/uygZzD8 Is there too little memory allocated to the modpack maybe? Can someone help please.    (T.T)馃挃
    • This is sad. Over 3300 people have checked the thread and no one is able to help or give any ideas :(.
  • Topics

  • Create New...

Important Information

By using this site, you agree to our Terms of Use.