Jump to content

[Solved][1.11.2] Using isRemote before Minecraft.getMinecraft can still cause a crash?


Recommended Posts

Posted (edited)

In my code I am trying to stop the player from moving when they are stunned. So using PlayerTickEvent I disable some of the keys used for movement.

Here is the code:

Spoiler

    @SubscribeEvent
    public void onPlayerTick(PlayerTickEvent event)
    {
        if (event.phase == TickEvent.Phase.START)
        {
            EntityPlayer player = event.player;
            IPlayerData playerData = PlayerDataProvider.getPlayerCapability(player);

            // Ensure the code within this if statement is only ran on Client
            if (player.world.isRemote)
            {
                // if this clients player is stunned, increment tickStunned and disable movement
                if (playerData.getIsStunned())
                {
                    playerData.setTicksStunned(playerData.getTicksStunned() + 1);

                    if (playerData.getTicksStunned() < playerData.getStunDuration())
                    {
                        // disable movement
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindForward.getKeyCode(), false);
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindBack.getKeyCode(), false);
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindLeft.getKeyCode(), false);
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindRight.getKeyCode(), false);
                    }
                    else
                    {
                        playerData.setIsStunned(false);
                        playerData.setTicksStunned(0);
                    }
                }

                return;
            }
    }

 

 

From what I understand is even if I use world.isRemote before using Minecraft.getMinecraft() this can still cause the server to crash, but it doesn't. I did test it on a dedicated server, but I was still running the server and client on the same computer idk if that affects it.

If using Minecraft.getMinecraft() even after making sure world.isRemote can cause a crash on the server, what's the proper way to go about this? Maybe create a method in my proxy to handle this, where the ServerProxy does nothing and ClientProxy has this code?

Edited by Kriptikz
Posted

The answer is "yes it will." The reason it isn't has to do with the fact that the server isn't even loading your class, which invalidates the test. 

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

Why wouldn't the server be loading the class? I do have other methods in this class I just only posted the piece I was wondering about. I also do register this for both client and server I'm pretty sure.

Here is the actual entire class:

Spoiler

public class ModEventHandler
{
    public static Field floatingTickCount = null;
    
    public ModEventHandler()
    {
        try
        {
            floatingTickCount = ReflectionHelper.findField(NetHandlerPlayServer.class, "floatingTickCount");
        } catch (Exception e)
        {
            System.out.println("Unable to find field floatingTickCount");
            e.printStackTrace();
        }
    }
    
	@SubscribeEvent
	public void onLivingEvent(LivingUpdateEvent event)
	{
		if (!event.getEntity().world.isRemote)
		{
			if (event.getEntityLiving() instanceof EntityLiving)
			{
				EntityLiving entity = (EntityLiving) event.getEntityLiving();
				IMobData mobData = MobDataProvider.getMobCapability(entity);
				if (entity.isAIDisabled())
				{
					mobData.setTicksStunned(mobData.getTicksStunned() + 1);
				}
				if (entity.isAIDisabled() && (mobData.getTicksStunned() % mobData.getStunnedDuration() == 0))
				{
					entity.setNoAI(false);
				}
			}
			
			if (event.getEntityLiving() instanceof EntityGhast)
			{

			}
			
			if (event.getEntityLiving() instanceof EntityMob)
			{
				EntityMob mob = (EntityMob) event.getEntityLiving();

				mob.targetTasks.addTask(0, new EntityAINearestAttackableTarget<>(mob, EntityDummyTarget.class, true));
			} 
		}

		
	}
	
	@SubscribeEvent
	public void onPlayerLogin(PlayerLoggedInEvent event)
	{
		EntityPlayer player = event.player;
		IPlayerData playerData = PlayerDataProvider.getPlayerCapability(player);

		MagicMastery.network.sendTo(new MessageSyncAllPlayerData(playerData), (EntityPlayerMP) player);
	}
	
	@SubscribeEvent
	public void onPlayerLoggout(PlayerLoggedOutEvent event)
	{
		
	}

    @SubscribeEvent
    public void onPlayerTick(PlayerTickEvent event)
    {
        if (event.phase == TickEvent.Phase.START)
        {
            EntityPlayer player = event.player;
            IPlayerData playerData = PlayerDataProvider.getPlayerCapability(player);

            // Check if on server and apply levitation code
            if (!player.world.isRemote)
            {
                if (playerData.getIsLevitating())
                {
                    // reset fall distance because technically they are
                    // levitating but minecraft thinks they are falling which
                    // means when they land they would take insane fall damage.
                    player.fallDistance = 0;

                    // prevent the player from getting kicked from the server
                    // for flying while using levitation spell.
                    if (player instanceof EntityPlayerMP)
                    {

                        try
                        {
                            floatingTickCount.setInt(((EntityPlayerMP) player).connection, 0);
                        } catch (IllegalAccessException e)
                        {
                            e.printStackTrace();
                        }

                    }

                    // decrease mana every second.
                    if (player.ticksExisted % 20 == 0)
                    {
                        if (playerData.getMana() - 2 >= 0)
                        {
                            playerData.setMana(playerData.getMana() - 2);
                        }
                        else
                        {
                            playerData.setIsLevitating(false);
                            MagicMastery.network.sendTo(new MessagePlayerIsLevitatingToClient(playerData.getIsLevitating()), (EntityPlayerMP) player);
                        }
                    }

                }
            }

            // Ensure the code within this if statement is only ran on Client
            if (player.world.isRemote)
            {
                if (Keybinds.levitate_down.isKeyDown())
                {
                    playerData.setLevitationAmp(1);
                }
                else if (Keybinds.levitate_up.isKeyDown())
                {
                    playerData.setLevitationAmp(9);
                }
                else
                {
                    playerData.setLevitationAmp(5);
                }

                if (playerData.getIsLevitating())
                {
                    player.motionY += (0.05D * (double) (playerData.getLevitationAmp() + 1) - player.motionY) * 0.2D;
                    player.fallDistance = 0;
                }

                // if this clients player is stunned, increment tickStunned and
                // disable all hotkey other than settings Gui key, open
                // inventory key, and swap items keys
                if (playerData.getIsStunned())
                {
                    playerData.setTicksStunned(playerData.getTicksStunned() + 1);

                    if (playerData.getTicksStunned() < playerData.getStunDuration())
                    {
                        // disable all hotkey other than settings Gui key, open
                        // inventory key, and swap items keys
                        //KeyBinding.unPressAllKeys();
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindForward.getKeyCode(), false);
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindBack.getKeyCode(), false);
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindLeft.getKeyCode(), false);
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindRight.getKeyCode(), false);
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindJump.getKeyCode(), false);
                        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindInventory.getKeyCode(), false);
                    }
                    else
                    {
                        playerData.setIsStunned(false);
                        playerData.setTicksStunned(0);
                    }
                }

                return;
            }

            // ensure player mana doesn't exceed player max mana every tick.
            // this makes adding mana though items or any other means easier to
            // handle. if any item sets players mana above the players max mana
            // it will be fixed on player tick (almost instantly).
            if (playerData.getMana() > playerData.getMaxMana())
            {
                playerData.setMana(playerData.getMaxMana());
            }

            // sync player mana every 5 ticks
            if (player.ticksExisted % 5 == 0)
            {
                MagicMastery.network.sendTo(new MessageSyncMana(playerData), (EntityPlayerMP) player);
            }

            // regen player mana every second
            if (player.ticksExisted % 20 == 0)
            {
                if ((playerData.getMana() + playerData.getManaRegenPerSecond()) <= playerData.getMaxMana())
                {
                    playerData.setMana(playerData.getMana() + playerData.getManaRegenPerSecond());
                }
            }

            // sync player selected spell to all tracking players every half
            // second.
            if (player.ticksExisted % 10 == 0)
            {
                EntityTracker entityTracker = ((WorldServer) player.world).getEntityTracker();
                entityTracker.sendToTracking(player,
                        MagicMastery.network.getPacketFrom(new MessageSyncSelectedSpellToTrackingClients(playerData.getSelectedSpell(), player)));
            }
        }

    }
}

 

 

Here is the @Mod class:

Spoiler

@Mod(modid = Reference.MODID, name = Reference.NAME, version = Reference.VERSION)
public class MagicMastery
{
	@SidedProxy(serverSide = Reference.SERVER_PROXY_CLASS, clientSide = Reference.CLIENT_PROXY_CLASS)
	public static IProxy proxy;
	
	@Instance(Reference.MODID)
	public static MagicMastery instance;
	
	public static SimpleNetworkWrapper network;
	
	@EventHandler
	public void preInit(FMLPreInitializationEvent event)
	{
		CapabilityManager.INSTANCE.register(IPlayerData.class, new PlayerDataStorage(), PlayerData.class);
		CapabilityManager.INSTANCE.register(IMobData.class, new MobDataStorage(), MobData.class);
		network = NetworkRegistry.INSTANCE.newSimpleChannel(Reference.MODID);
		
		ModMessages.registerMessages();
		ModEntities.init();
		
		proxy.preInit();
	}
	
	@EventHandler
	public void init(FMLInitializationEvent event)
	{
		MinecraftForge.EVENT_BUS.register(new AttachCapabilityHandler());
		MinecraftForge.EVENT_BUS.register(new ModEventHandler());
		
		NetworkRegistry.INSTANCE.registerGuiHandler(instance, new GuiHandler());
		proxy.init();
	}
	
	@EventHandler
	public void postInit(FMLPostInitializationEvent event)
	{
		
		proxy.postInit();
	}	
}

 

 

Posted
2 hours ago, Kriptikz said:

Maybe create a method in my proxy to handle this, where the ServerProxy does nothing and ClientProxy has this code?

This is the proper approach. Create a method in your proxy which returns the Minecraft instance on the Client-side only, then use this in your code after the isRemote check. The Server-side implementation should really throw an exception (since the method must never be called server-side).

Posted
16 hours ago, Kriptikz said:

still no idea why it doesn't crash

You said it yourself up above: You had both server and client running on the same machine, so the client was there to load the Minecraft class. As long as the class is loaded in the JVM, the server can load with a reference to a class that it would not load for itself (because class Minecraft is client side-only).

 

It's probably the most common source of "My mod worked in Eclipse and SP but blew a gasket as soon as I tried it in true MP" threads that run like a rash throughout this help forum. I myself tripped over class Minecraft's client-only restriction in my first mod and found help in threads going back to 1.6.2 and earlier.

 

Someday this forum will have a dynamic FAQ AI that detects that predictable error text in the crash report and sends a stock reply plus an admonition to Google the error message to see the thousands (ok, hundreds) of identical past threads. Until then, each newbie has the privilege of repeating the lore to the next who comes along -- so you're now the officer of the watch, please field the next instance (which will probably come within the next week or two).

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted
17 hours ago, Jay Avery said:

Create a method in your proxy which returns the Minecraft instance

Returns? That could lead to the same sort of reference to a missing class. I recommend a proxy method that uses the Minecraft class to do what needs doing client-side (if indeed that's even the best way to design this mod).

 

Looking at that design, it doesn't fit with "proper" client-server purposes. The server is the authority, and the client is the UI. Therefore, if the "stun" effect is to prevent player movement, it should do its work on the server (the authority). It should not hack the keys (or even trust a player to be limited by them). In theory, a devious player could have a second set of movement controls (e.g. a joystick mod) to continue moving, and your server-side would not be enforcing the stun.

 

I hate to say it, but it looks like you should go back to the drawing board and find a hook server side to do what you want.

  • Like 1

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted
3 minutes ago, jeffryfisher said:

Looking at that design, it doesn't fit with "proper" client-server purposes. The server is the authority, and the client is the UI. Therefore, if the "stun" effect is to prevent player movement, it should do its work on the server (the authority). It should not hack the keys (or even trust a player to be limited by them). In theory, a devious player could have a second set of movement controls (e.g. a joystick mod) to continue moving, and your server-side would not be enforcing the stun.

Yea I figured this could end up becoming a problem. From what I understand the client is what moves the player and the server validates that movement correct? But yea, back to the drawing board.

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

    • Reach Out To Rapid Digital: What sapp Info: +1 41 4 80 7 14 85 Email INFO: rap iddi gita lrecov ery @ exe cs. com Hello, my name is Jayson, and I’m 35 years old from the United Kingdom. My family and I recently endured an incredibly challenging experience that I wouldn’t wish on anyone. We became victims of a cryptocurrency investment fraud scheme that saw us lose a staggering $807,000 in USDT and Bitcoins. The fraudsters had created a convincing facade, and we were lured into investing, only to discover later that the platform was a complete scam. We were left devastated, not just financially, but emotionally, as we had trusted these people and believed in the legitimacy of the investment. After the initial shock wore off, we desperately searched for ways to recover the lost funds. It seemed like an impossible task, and we felt as though there was no hope. That’s when, by sheer luck, we stumbled across a post about Rapid Digital Recovery, a cryptocurrency and funds recovery organization with a proven track record in cybersecurity and fraud recovery. We decided to reach out to them, and from the first interaction, we were impressed with their professionalism and transparency. They explained the recovery process in detail and reassured us that they had the skills and expertise to track down the perpetrators and recover our funds. This gave us a renewed sense of hope, something we hadn’t felt in months. What truly stood out during our experience with Rapid Digital Recovery was their dedication to the recovery process. The team went above and beyond, using sophisticated tracking tools and cyber forensics to gather critical information. Within a matter of weeks, they had successfully located the funds and traced the scam back to the fraudsters responsible. They worked with the authorities to ensure the criminals were held accountable for their actions. To our relief, the team at Rapid Digital Recovery was able to recover every single penny we had lost. The funds were returned in full, and the sense of closure we felt was invaluable. We couldn’t have imagined such a positive outcome in the early stages of our recovery journey, and we are deeply grateful for the work they did. If you ever find yourself in a similar situation, I highly recommend contacting Rapid Digital Recovery. Their expertise, transparency, and dedication to their clients make them the go-to choice for anyone seeking to recover lost cryptocurrency or funds. They truly gave us back our financial future.  
    • This is my first time modding anything, so maybe just skill issue. I'm using Forge 54.0.12 and Temurin 21.0.5+11-LTS I wanted to create a custom keybind and to check whether it works I'd like to send a chat message. I tried using Minecraft.getInstance().player.sendSystemMessage(Component.literal("test")); but IntelliJ couldnt resolve sendSystemMessage(...). Since I saw people using it in earlier versions, I tried the same thing with 1.20.6(- 50.1.0), where it works fine, now I can't figure out if this is intentional and whether there are other options for sending chat messages. On that note, is there more documentation than https://docs.minecraftforge.net/en/1.21.x/? It seems very incomplete compared to something like the Oracle Java docs
    • Hi, i'm having this error and I wanna fix it. we try: -Reload drivers -Eliminate .minecraft -Eliminate Java -Restart launcher -Verify if minecraft is using gpu -Mods  in .minecraft is empty -Install the latest and recomended version of forge idk what i have to do, help me pls. the lastest log is: https://mclo.gs/WAMao8x  
    • Read the FAQ, Rule #2. (https://forums.minecraftforge.net/topic/125488-rules-and-frequently-asked-questions-faq/)  
  • Topics

×
×
  • Create New...

Important Information

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