As the title says, whenever I have a while(true) { loop or a for( ; ; ) loop it causes the game to freeze. Not like, crash freeze, it just causes me not to be able to manipulate anything in the world.
public class StarCatcherT1 extends BlockDispenser
{
private final IBehaviorDefaultDispenseSpecificItem field_149947_P = new IBehaviorDefaultDispenseSpecificItem();
private static final String __OBFID = "CL_00000233";
private final long PERIOD = 1000L; // Adjust to suit timing
long lastTime = System.currentTimeMillis() - PERIOD;
/**
* Returns a new instance of a block's tile entity class. Called on placing the block.
*/
public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_)
{
return new TileEntityDropper();
}
protected void func_149941_e(World p_149941_1_, int p_149941_2_, int p_149941_3_, int p_149941_4_)
{
BlockSourceImpl var5 = new BlockSourceImpl(p_149941_1_, p_149941_2_, p_149941_3_, p_149941_4_);
TileEntityDispenser var6 = (TileEntityDispenser)var5.getBlockTileEntity();
if (var6 != null)
{
int var7 = var6.func_146017_i();
Yes.
I just need to find an infinite loop that doesn't freeze the game.
You're holding the game thread up in your loop. If you want an infinite loop, you'll have to run the loop on a new thread, but then you'll also have to worry about synchronization needed with concurrency.
You're holding the game thread up in your loop. If you want an infinite loop, you'll have to run the loop on a new thread, but then you'll also have to worry about synchronization needed with concurrency.
How would one go about creating a new thread? I'm new to modding, so please forgive my inexperience.
As the title says, whenever I have a while(true) { loop or a for( ; ; ) loop it causes the game to freeze. Not like, crash freeze, it just causes me not to be able to manipulate anything in the world.
public class StarCatcherT1 extends BlockDispenser
{
private final IBehaviorDefaultDispenseSpecificItem field_149947_P = new IBehaviorDefaultDispenseSpecificItem();
private static final String __OBFID = "CL_00000233";
private final long PERIOD = 1000L; // Adjust to suit timing
long lastTime = System.currentTimeMillis() - PERIOD;
/**
* Returns a new instance of a block's tile entity class. Called on placing the block.
*/
public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_)
{
return new TileEntityDropper();
}
protected void func_149941_e(World p_149941_1_, int p_149941_2_, int p_149941_3_, int p_149941_4_)
{
BlockSourceImpl var5 = new BlockSourceImpl(p_149941_1_, p_149941_2_, p_149941_3_, p_149941_4_);
TileEntityDispenser var6 = (TileEntityDispenser)var5.getBlockTileEntity();
if (var6 != null)
{
int var7 = var6.func_146017_i();
Based on what you're trying to achieve, I take it you're wanting to do something every tick in game? Like, have your code constantly running?
If so, while loops won't help. The game runs on a thread, which is a managed loop, sort of. Whenever you execute a loop, you interrupt the game's thread, and it won't start back up till your loop is broken out of (either by issuing a break command or by ending the loop naturally). Because you've got an infinite loop, your loop never stops. So the JVM is stuck inside your code executing it over and over, thus, it can't call the rest of the game's code, therefore, the game locks up on you.
Now, before I explain what you SHOULD do, I'll explain how the game works internally. Every time the loop reiterates through the code (reloops through the code, if you will), the game has a bunch of event-like methods and classes responding. This concept is known as ticking. A tick is essentially one update to the game's code. The thread is clocked to 20 times per second, so the game ticks 20 times per second, ie the code is being executed and reran 20 times every second.
Forge has a feature called events. An event is exactly as it sounds, it's an event that happens in the game, whether that be hitting a block or hurting an entity, or more internal and advanced things like chunks loading and unloading, or an entity being constructed. You can subscribe any method of yours to a specific event (or set of events that have a main common event, say any living entity event, they all have a common base, LivingEvent IIRC, you can subscribe to this to run your code on ANY event that is of this type). When you subscribe to it, and register the class your method and subscription is in, it gets added to the Event Bus (basically a list, if you will). When an event happens in the game, Forge goes through and fires all subscribed methods that are subscribed to this event, so your code will be ran when the event you're subscribed to occurs.
Now, Forge has this thing called a TickEvent, which is event that is fired every tick. You can use this to automatically run any code you wish whenever the game ticks / updates.
Now, I do realise that you said you solved the issue, however I thought I should perhaps suggest a better / more official way of doing so. IMO, running your code on a separate thread, especially for your purpose, is highly inefficient, as you need to take into consideration things such as synchronisation, fields, instances, etc, at the end of the day, IMO way too much work for what it's worth, when you could do something which is much easier and more official and supported, which would give you a better effect and better performance when you get down to it.
Rollback Post to RevisionRollBack
Author of the Clarity, Serenity, Sapphire & Halcyon shader packs for Minecraft: Java Edition.
Based on what you're trying to achieve, I take it you're wanting to do something every tick in game? Like, have your code constantly running?
If so, while loops won't help. The game runs on a thread, which is a managed loop, sort of. Whenever you execute a loop, you interrupt the game's thread, and it won't start back up till your loop is broken out of (either by issuing a break command or by ending the loop naturally). Because you've got an infinite loop, your loop never stops. So the JVM is stuck inside your code executing it over and over, thus, it can't call the rest of the game's code, therefore, the game locks up on you.
Now, before I explain what you SHOULD do, I'll explain how the game works internally. Every time the loop reiterates through the code (reloops through the code, if you will), the game has a bunch of event-like methods and classes responding. This concept is known as ticking. A tick is essentially one update to the game's code. The thread is clocked to 20 times per second, so the game ticks 20 times per second, ie the code is being executed and reran 20 times every second.
Forge has a feature called events. An event is exactly as it sounds, it's an event that happens in the game, whether that be hitting a block or hurting an entity, or more internal and advanced things like chunks loading and unloading, or an entity being constructed. You can subscribe any method of yours to a specific event (or set of events that have a main common event, say any living entity event, they all have a common base, LivingEvent IIRC, you can subscribe to this to run your code on ANY event that is of this type). When you subscribe to it, and register the class your method and subscription is in, it gets added to the Event Bus (basically a list, if you will). When an event happens in the game, Forge goes through and fires all subscribed methods that are subscribed to this event, so your code will be ran when the event you're subscribed to occurs.
Now, Forge has this thing called a TickEvent, which is event that is fired every tick. You can use this to automatically run any code you wish whenever the game ticks / updates.
Now, I do realise that you said you solved the issue, however I thought I should perhaps suggest a better / more official way of doing so. IMO, running your code on a separate thread, especially for your purpose, is highly inefficient, as you need to take into consideration things such as synchronisation, fields, instances, etc, at the end of the day, IMO way too much work for what it's worth, when you could do something which is much easier and more official and supported, which would give you a better effect and better performance when you get down to it.
Thanks! I hadn't quite understood how Events worked, so I kinda avoided them until I learned how. Turns out I needed them for this. I currently have it looping every ten-some minutes with a delayed while loop, though this would probably make the code neater and less laggy.
Here is the source code:
import java.util.Random;
import com.astralmagicmod.block.AMBlock.IBehaviorDispenseSpecificItem;
import com.astralmagicmod.block.starcatcher.IBehaviorDefaultDispenseSpecificItem;
import com.astralmagicmod.lib.AstralMagicMod;
import com.sun.org.apache.xerces.internal.impl.xpath.XPath.Axis;
import net.minecraft.block.Block;
import net.minecraft.block.BlockDispenser;
import net.minecraft.block.BlockSourceImpl;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.dispenser.BehaviorDefaultDispenseItem;
import net.minecraft.dispenser.IBehaviorDispenseItem;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.tileentity.TileEntityDropper;
import net.minecraft.tileentity.TileEntityHopper;
import net.minecraft.util.Facing;
import net.minecraft.world.World;
public class StarCatcherT1 extends BlockDispenser
{
private final IBehaviorDefaultDispenseSpecificItem field_149947_P = new IBehaviorDefaultDispenseSpecificItem();
private static final String __OBFID = "CL_00000233";
private final long PERIOD = 1000L; // Adjust to suit timing
long lastTime = System.currentTimeMillis() - PERIOD;
public void registerBlockIcons(IIconRegister p_149651_1_)
{
this.blockIcon = p_149651_1_.registerIcon(AstralMagicMod.MODID + ":OakPlank");
this.field_149944_M = p_149651_1_.registerIcon(AstralMagicMod.MODID + ":OakPlank");
this.field_149945_N = p_149651_1_.registerIcon(AstralMagicMod.MODID + ":WeakStarCatcherFront");
this.field_149946_O = p_149651_1_.registerIcon(AstralMagicMod.MODID + ":WeakStarCatcherBottom");
}
protected IBehaviorDispenseItem func_149940_a(ItemStack p_149940_1_)
{
return this.field_149947_P;
}
/**
* Returns a new instance of a block's tile entity class. Called on placing the block.
*/
public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_)
{
return new TileEntityDropper();
}
protected void func_149941_e(World p_149941_1_, int p_149941_2_, int p_149941_3_, int p_149941_4_)
{
BlockSourceImpl var5 = new BlockSourceImpl(p_149941_1_, p_149941_2_, p_149941_3_, p_149941_4_);
TileEntityDispenser var6 = (TileEntityDispenser)var5.getBlockTileEntity();
if (var6 != null)
{
int var7 = var6.func_146017_i();
if (var7 < 0)
{
p_149941_1_.playAuxSFX(1001, p_149941_2_, p_149941_3_, p_149941_4_, 0);
}
else
{
ItemStack var8 = var6.getStackInSlot(var7);
int var9 = p_149941_1_.getBlockMetadata(p_149941_2_, p_149941_3_, p_149941_4_) & 7;
IInventory var10 = TileEntityHopper.func_145893_b(p_149941_1_, (double)(p_149941_2_ + Facing.offsetsXForSide[var9]), (double)(p_149941_3_ + Facing.offsetsYForSide[var9]), (double)(p_149941_4_ + Facing.offsetsZForSide[var9]));
ItemStack var11 = null;
if (var10 != null)
{
var11 = TileEntityHopper.func_145889_a(var10, var8.copy().splitStack(1), Facing.oppositeSide[var9]);
if (var11 == null)
{
var11 = var8.copy();
if (--var11.stackSize == 0)
{
var11 = null;
}
}
else
{
var11 = var8.copy();
}
}
else
{
//note a single Random object is reused here
while(true) {
long thisTime = System.currentTimeMillis();
boolean onTickInGame;{
if ((thisTime - lastTime) >= PERIOD) {
//var11 = this.field_149947_P.dispense(var5, var8);
p_149941_1_.spawnEntityInWorld(new EntityItem(p_149941_1_, p_149941_2_, p_149941_3_ - 1, p_149941_4_, new ItemStack(AMBlock.lesserStar)));
lastTime = thisTime;
}}}
}
}}
ItemStack var111 = new ItemStack(AMBlock.debugBlock, 576);
var111.stackSize = 64;
}}
I know the problem is the "while(true) {" in this section of code, i just don't know how to fix it.
while(true) {
long thisTime = System.currentTimeMillis();
boolean onTickInGame;{
if ((thisTime - lastTime) >= PERIOD) {
//var11 = this.field_149947_P.dispense(var5, var8);
p_149941_1_.spawnEntityInWorld(new EntityItem(p_149941_1_, p_149941_2_, p_149941_3_ - 1, p_149941_4_, new ItemStack(AMBlock.lesserStar)));
lastTime = thisTime;
Also, there are supposedly no errors in the code.
I just need to find an infinite loop that doesn't freeze the game.
You're holding the game thread up in your loop. If you want an infinite loop, you'll have to run the loop on a new thread, but then you'll also have to worry about synchronization needed with concurrency.
How would one go about creating a new thread? I'm new to modding, so please forgive my inexperience.
Updated source code:
Based on what you're trying to achieve, I take it you're wanting to do something every tick in game? Like, have your code constantly running?
If so, while loops won't help. The game runs on a thread, which is a managed loop, sort of. Whenever you execute a loop, you interrupt the game's thread, and it won't start back up till your loop is broken out of (either by issuing a break command or by ending the loop naturally). Because you've got an infinite loop, your loop never stops. So the JVM is stuck inside your code executing it over and over, thus, it can't call the rest of the game's code, therefore, the game locks up on you.
Now, before I explain what you SHOULD do, I'll explain how the game works internally. Every time the loop reiterates through the code (reloops through the code, if you will), the game has a bunch of event-like methods and classes responding. This concept is known as ticking. A tick is essentially one update to the game's code. The thread is clocked to 20 times per second, so the game ticks 20 times per second, ie the code is being executed and reran 20 times every second.
Forge has a feature called events. An event is exactly as it sounds, it's an event that happens in the game, whether that be hitting a block or hurting an entity, or more internal and advanced things like chunks loading and unloading, or an entity being constructed. You can subscribe any method of yours to a specific event (or set of events that have a main common event, say any living entity event, they all have a common base, LivingEvent IIRC, you can subscribe to this to run your code on ANY event that is of this type). When you subscribe to it, and register the class your method and subscription is in, it gets added to the Event Bus (basically a list, if you will). When an event happens in the game, Forge goes through and fires all subscribed methods that are subscribed to this event, so your code will be ran when the event you're subscribed to occurs.
Now, Forge has this thing called a TickEvent, which is event that is fired every tick. You can use this to automatically run any code you wish whenever the game ticks / updates.
Now, I do realise that you said you solved the issue, however I thought I should perhaps suggest a better / more official way of doing so. IMO, running your code on a separate thread, especially for your purpose, is highly inefficient, as you need to take into consideration things such as synchronisation, fields, instances, etc, at the end of the day, IMO way too much work for what it's worth, when you could do something which is much easier and more official and supported, which would give you a better effect and better performance when you get down to it.
Author of the Clarity, Serenity, Sapphire & Halcyon shader packs for Minecraft: Java Edition.
My Github page.
The entire Minecraft shader development community now has its own Discord server! Feel free to join and chat with all the developers!
Thanks! I hadn't quite understood how Events worked, so I kinda avoided them until I learned how. Turns out I needed them for this. I currently have it looping every ten-some minutes with a delayed while loop, though this would probably make the code neater and less laggy.