Jump to content

In game skin changer only works in dev environment


Dijkstra
 Share

Recommended Posts

I am making a mod that allows the user to change there skin game, it far from complete, but bubbled it down to just setting a skin me and sister to test on my server for performance and we both ended up with are skin set on minecraft.net, but in my dev  environment my skin does change to the one i set the set of code i am test is

 

 

package dijkstra.wardrobe.main;
public class testReflections{
public static ResourceLocation oldSkin;
public static AbstractClientPlayer player = Minecraft.getMinecraft().thePlayer;
public static void load(){
	Class Skin = AbstractClientPlayer.class;
	try {
		Field locationSkin = AbstractClientPlayer.class.getDeclaredField("locationSkin");
		locationSkin.setAccessible(true);
		locationSkin.set(Minecraft.getMinecraft().thePlayer, setSkin(Players.valueOf(player.getDisplayName())));
	}
	catch (Exception e){
		e.printStackTrace();
	}
}
private static ResourceLocation setSkin(Players player){
	switch(player){
	case Dijkstra:
		return new ResourceLocation("textures/players/Dijkstra.png");
	case Pegasus:
		return new ResourceLocation("textures/players/Pegasus.png");
	default:
		return null;
	}
}
private enum Players{
	Dijkstra,
	Pegasus
}

}

 

 

events

 

package dijkstra.wardrobe.main;

public class eventHandler{
public static boolean changed = true;
    @SubscribeEvent
    public void renderTick(TickEvent.RenderTickEvent event)
    {
        Minecraft mc = Minecraft.getMinecraft();

        if(mc.theWorld != null)
        {
            if(event.phase == TickEvent.Phase.START)
            {
            	if(changed){
            		testReflections.load();
            		changed = false;
            	}
            	
            }
        }
    }
    
    @SubscribeEvent
public void PlayerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event){
    	changed = true;
    }
}

 

main file

 

@EventHandler
public static void PreLoad(FMLPreInitializationEvent PreEvent){
	FMLCommonHandler.instance().bus().register(new eventHandler());
	proxy.registerRenderInfo();
}

 

 

Think that should be all you need if need more of the mod just ask but it is getting quite large

Link to comment
Share on other sites

In the obfuscated (non-development) environment, there's no field called

locationSkin

; instead it has the SRG name

field_110312_d

.

 

FML's

ObfuscationReflectionHelper#setPrivateValue

allows you to pass both the deobfuscated (MCP) and obfuscated (SRG) names of the field to set the value of. Either use it directly or adapt the logic to your class.

 

Make sure you only reference client-only classes like

Minecraft

and

AbstractClientPlayer

from client-side code (i.e. only register your event handler in your client proxy).

 

Edit: The SRG name of

AbstractClientPlayer#locationSkin

in 1.7.10 is actually

field_110312_d

.

field_178865_e

is the SRG name of

NetworkPlayerInfo#locationSkin

field in 1.8.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Ok so done use fml method still works fine in the dev environment but now crashes out of the dev environment

 

crash report out of dev

 

cpw.mods.fml.relauncher.ReflectionHelper$UnableToAccessFieldException: cpw.mods.fml.relauncher.ReflectionHelper$UnableToFindFieldException: java.lang.NoSuchFieldException: locationSkin

at cpw.mods.fml.relauncher.ReflectionHelper.setPrivateValue(ReflectionHelper.java:147)

at cpw.mods.fml.common.ObfuscationReflectionHelper.setPrivateValue(ObfuscationReflectionHelper.java:91)

at dijkstra.wardrobe.main.testReflections.load(testReflections.java:15)

at dijkstra.wardrobe.main.eventHandler.renderTick(eventHandler.java:23)

at cpw.mods.fml.common.eventhandler.ASMEventHandler_7_eventHandler_renderTick_RenderTickEvent.invoke(.dynamic)

at cpw.mods.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:54)

at cpw.mods.fml.common.eventhandler.EventBus.post(EventBus.java:138)

at cpw.mods.fml.common.FMLCommonHandler.onRenderTickStart(FMLCommonHandler.java:335)

at net.minecraft.client.Minecraft.func_71411_J(Minecraft.java:999)

at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:898)

at net.minecraft.client.main.Main.main(SourceFile:148)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:483)

at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)

at net.minecraft.launchwrapper.Launch.main(Launch.java:28)

Caused by: cpw.mods.fml.relauncher.ReflectionHelper$UnableToFindFieldException: java.lang.NoSuchFieldException: locationSkin

at cpw.mods.fml.relauncher.ReflectionHelper.findField(ReflectionHelper.java:94)

at cpw.mods.fml.relauncher.ReflectionHelper.setPrivateValue(ReflectionHelper.java:143)

... 16 more

Caused by: java.lang.NoSuchFieldException: locationSkin

at java.lang.Class.getDeclaredField(Class.java:2062)

at cpw.mods.fml.relauncher.ReflectionHelper.findField(ReflectionHelper.java:85)

... 17 more

 

 

 

Link to comment
Share on other sites

To answer the question in your previous post, only use reflection when you can't use a normal method call/field access. Examples of this include accessing non-public methods/fields or methods/fields with a dynamic name/argument list and instantiating a class that's only known at runtime (i.e. you have a

Class

object you want to create an instance of).

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Ok so done use fml method still works fine in the dev environment but now crashes out of the dev environment

 

crash report out of dev

 

cpw.mods.fml.relauncher.ReflectionHelper$UnableToAccessFieldException: cpw.mods.fml.relauncher.ReflectionHelper$UnableToFindFieldException: java.lang.NoSuchFieldException: locationSkin

at cpw.mods.fml.relauncher.ReflectionHelper.setPrivateValue(ReflectionHelper.java:147)

at cpw.mods.fml.common.ObfuscationReflectionHelper.setPrivateValue(ObfuscationReflectionHelper.java:91)

at dijkstra.wardrobe.main.testReflections.load(testReflections.java:15)

at dijkstra.wardrobe.main.eventHandler.renderTick(eventHandler.java:23)

at cpw.mods.fml.common.eventhandler.ASMEventHandler_7_eventHandler_renderTick_RenderTickEvent.invoke(.dynamic)

at cpw.mods.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:54)

at cpw.mods.fml.common.eventhandler.EventBus.post(EventBus.java:138)

at cpw.mods.fml.common.FMLCommonHandler.onRenderTickStart(FMLCommonHandler.java:335)

at net.minecraft.client.Minecraft.func_71411_J(Minecraft.java:999)

at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:898)

at net.minecraft.client.main.Main.main(SourceFile:148)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:483)

at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)

at net.minecraft.launchwrapper.Launch.main(Launch.java:28)

Caused by: cpw.mods.fml.relauncher.ReflectionHelper$UnableToFindFieldException: java.lang.NoSuchFieldException: locationSkin

at cpw.mods.fml.relauncher.ReflectionHelper.findField(ReflectionHelper.java:94)

at cpw.mods.fml.relauncher.ReflectionHelper.setPrivateValue(ReflectionHelper.java:143)

... 16 more

Caused by: java.lang.NoSuchFieldException: locationSkin

at java.lang.Class.getDeclaredField(Class.java:2062)

at cpw.mods.fml.relauncher.ReflectionHelper.findField(ReflectionHelper.java:85)

... 17 more

 

 

 

This is the same error as before: you're only using the deobfucated (MCP) name, not the obfuscated (SRG) name. You need to pass both names to

ObfuscationReflectionHelper.getPrivateValue

(and other methods in the same class that take a

String

array/vararg of field names).

 

You can find the SRG name of a method/field in the MCP mapping CSVs, which can be found in your Gradle cache. For recent 1.7.10 versions of Forge, the CSVs are in  ~/.gradle/caches/minecraft/net/minecraftforge/forge/<forge_version>/unpacked/conf (replace ~ with %USERPROFILE% on Windows). You can also download the mappings from the MCPBot Website.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

public static void load(){
	AbstractClientPlayer player = Minecraft.getMinecraft().thePlayer;
	ResourceLocation skin = new ResourceLocation("textures/players/"+player.getDisplayName()+".png");
	ObfuscationReflectionHelper.setPrivateValue(AbstractClientPlayer.class, player, skin, new String[]{"locationSkin","field_178865_e"});

}

 

this is code i am using, clearly i am doing something but can not work it out  i have passed in both the dev name and real, still works fine in dev but not out of dev

Link to comment
Share on other sites

Ah, I gave you the SRG name of 1.8's

NetworkPlayerInfo#locationSkin

field instead of 1.7.10's

AbstractClientPlayer#locationSkin

field. The SRG name you want is actually

field_110312_d

.

 

In future you should include the Minecraft version in the title so people know which version you're working with.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Skins are downloaded and applied to players asynchronously, so you can't immediately replace the player's skin with your custom skin.

 

When an

AbstractClientPlayer

is instantiated, it calls

SkinManager#func_152790_a

. This downloads the the name of the player's skin and cape textures from Mojang's session servers and calls

SkinManager#func_152789_a

for each one. This downloads the texture in a separate thread (if it hasn't already been downloaded) and then calls

SkinManager.SkinAvailableCallback#func_152121_a

(implemented by

AbstractClientPlayer

) on the next tick to store the

ResourceLocation

of the texture in the appropriate field of

AbstractClientPlayer

.

 

I'd recommend subscribing to

EntityJoinWorldEvent

(only on the client side) and checking if the entity is an

AbstractClientPlayer

. If it is, call

SkinManager#func_152790_a

with your own implementation of

SkinManager.SkinAvailableCallback#func_152121_a

that that the

Type

is

Type.SKIN

and then sets the player's

locationSkin

field.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

  • 4 weeks later...

Sorry i have not got back sooner, but I have be busy with more important stuff.

 

 

I used to get the skin manager instance from the Minecraft class

 

SkinManager sm = Minecraft.getMinecraft().func_152342_ad();

 

so that i can call

 

SkinCallback sc = new SkinCallback(); // my class that implements SkinAvailableCallback 
sm.func_152790_a(GameProfile, sc, false);

 

but i am sure where to get the game profile class or the what to set boolean to

Link to comment
Share on other sites

Use

EntityPlayer#getGameProfile

to get a player's

GameProfile

.

 

The

boolean

is whether the downloaded texture names need to be securely signed.

AbstractClientPlayer

passes

true

, you probably should too.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

I have subscribed to both PlayerLoggedInEvent and the EntityJoinWorldEvent, but i have a problem the EntityJoinWorldEvent is not trigger by a player and the PlayerLoggedInEvent gives me an EntityPlayer and not an abstract client player and i can not cast the  EntityPlayer to an abstract client player

Link to comment
Share on other sites

I have subscribed to both PlayerLoggedInEvent and the EntityJoinWorldEvent, but i have a problem the EntityJoinWorldEvent is not trigger by a player and the PlayerLoggedInEvent gives me an EntityPlayer and not an abstract client player and i can not cast the  EntityPlayer to an abstract client player

 

Wrong. EntityJoinWorldEvent is triggered by all entities joining the world, hence the name. Subscribe to the EntityJoinWorldEvent, check the instance of the AbstractClientPlayer against the event.entity, and then cast and do whatever you need. Remember, changing the skin with reflection during the EntityJoinWorldEvent will result in a NullPointerException (if you are changing NetworkPlayerInfo.locationSkin), so you will need to create a delayed runnable and schedule it to run on the main thread. Be sure to use ObfuscationReflectionHelper with SRG names.

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Link to comment
Share on other sites

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
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.

 Share



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I made a huge forge 1.7.10 mod pack but whenever I try to create a singleplayer world I get the error saying "A fatal error has occurred, this connection is terminated." Does anyone know what the issue could be?  Here is my fml-client-latest.log from when it crashes: https://paste.ubuntu.com/p/3rKSJSqnrX/ and here is the list of mods: https://imgur.com/a/AZifMbg    
    • Im trying to host a minecraft server using the curseforge serverpack from FTB Direwolf20 and when I try to start the server I run into an error The Error: Starting server A problem occurred running the Server launcher.java.lang.reflect.InvocationTargetException         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)         at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)         at java.lang.reflect.Method.invoke(Unknown Source)         at cpw.mods.fml.relauncher.ServerLaunchWrapper.run(ServerLaunchWrapper.java:43)         at cpw.mods.fml.relauncher.ServerLaunchWrapper.main(ServerLaunchWrapper.java:12) Caused by: java.lang.NoClassDefFoundError: org/apache/logging/log4j/Level         at net.minecraft.launchwrapper.Launch.launch(Launch.java:94)         at net.minecraft.launchwrapper.Launch.main(Launch.java:28)         ... 6 more Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.Level         at java.net.URLClassLoader$1.run(Unknown Source)         at java.net.URLClassLoader$1.run(Unknown Source)         at java.security.AccessController.doPrivileged(Native Method)         at java.net.URLClassLoader.findClass(Unknown Source)         at java.lang.ClassLoader.loadClass(Unknown Source)         at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)         at java.lang.ClassLoader.loadClass(Unknown Source)         ... 8 more   I'have tried deleting and downloading the newset version of java wich didnt work and now im using an older version which is the 1.7.0_80 Here is what my Server folder looks like: https://ibb.co/jkbfRY7 Here is what the ServerStart.bat file looks like: @if NOT "%FTB_VERBOSE%"=="yes" ( @echo off ) call settings.bat if NOT EXIST minecraft_server.1.7.10.jar ( goto install ) if NOT EXIST libraries\%LAUNCHWRAPPER% ( goto install ) goto skipinstall :install echo running install script! call FTBInstall.bat :skipinstall REM Check if java in path REM TODO: use %JAVACMD% where java > NUL 2>&1 if %ERRORLEVEL% NEQ 0 ( echo No java binary in path. Can't run server, exiting... pause exit /B ) REM Test JVM REM e.g. 32-bit JVM does not have server\jvm.dll library java -server -version > java-test.log 2>&1 if %ERRORLEVEL% NEQ 0 ( echo Detected following JVM error: echo ======================================= more java-test.log echo ======================================= echo JVM test failed. Can't run server, Exiting... pause exit /B ) if not exist eula.txt ( echo Missing eula.txt. Startup will fail and eula.txt will be created echo Make sure to read eula.txt before playing! goto startserver ) find "eula=false" eula.txt 1 > NUL 2>&1 if %ERRORLEVEL% EQU 0 ( echo Make sure to read eula.txt before playing! Exiting. pause exit /B ) del /f /q autostart.stamp > nul 2>1 :startserver echo Starting server java -server -Xms512M -Xmx2048M -XX:PermSize=256M -XX:+UseParNewGC -XX:+CMSIncrementalPacing -XX:+CMSClassUnloadingEnabled -XX:ParallelGCThreads=2 -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10 -jar FTBServer-1.7.10-1558.jar nogui :server_loop if exist autostart.stamp ( del /f /q autostart.stamp > nul 2>1 echo If you want to completely stop the server process now, press Ctrl+C before the time is up! for /l %%i in (5,-1,1) do ( echo Restarting server in %%i choice /t 1 /d y > nul ) echo Starting server now java -server -Xms512M -Xmx2048M -XX:PermSize=256M -XX:+UseParNewGC -XX:+CMSIncrementalPacing -XX:+CMSClassUnloadingEnabled -XX:ParallelGCThreads=2 -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10 -jar FTBServer-1.7.10-1558.jar nogui echo Server process finished goto :server_loop ) echo Exiting... pause  
    • Made a modpack (Well Rounded Blockheads, in case the modlist on curseforge helps) and server to host it, worked fine until last night. The issue that pops up after some days being up/working is when you leave a world (singleplayer) or shutdown a server, the process hangs and jumps to 8.5gb ram used, eats up CPU usage (50-60% in taskman on a 3800x) and just sits there. If done on a single player world, the game doesnt fully crash, (e.g. if you alt+f4 buttons like save and quit, options stay in the window, are still clickable but they do nothing) Saving seems to still happen, as location/inventory updates if I restart server or client and play the world again.   If I start the currently afflicted server but dont login the server closes properly, its only once I log back in the problem occurs. Its a priv server and I dont have anyone else to test atm so Idk if its a prob with my player or players/area in general. Only recent changes in game are the additions of a pnuematicraft pressure chamber, an enchanting table, and bookshelves from builders crafts and additions.... I've been trying to get help on this all day, so ANY assistance goes a long way, even if its a way to debug this myself >~< Debug/Latest logs
    • Thanks warjort. I was afraid, that this is because they are entities. Now I know where to dig. But what about water, for example? I have checked via debug code, that there is no entity there (appropriate method return null). What is wrong with liquids?
  • Topics

×
×
  • Create New...

Important Information

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