Line 31: |
Line 31: |
| === Sided Setup Events === | | === Sided Setup Events === |
| | | |
− | There are different events which are fired at different stages during the [[Modloading|modloading process]]. Most of these events are fired on both physical sides, except for the '''sided setup events''': <code>FMLClientSetupEvent</code> and <code>FMLDedicatedServerSetupEvent</code>, which is fired on the physical client and the physical/dedicated server respectively. | + | There are different events which are fired at different stages during the [[Stages_of_Modloading|modloading process]]. Most of these events are fired on both physical sides, except for the '''sided setup events''': <code>FMLClientSetupEvent</code> and <code>FMLDedicatedServerSetupEvent</code>, which is fired on the physical client and the physical/dedicated server respectively. |
| | | |
| These events should be used for running side-specific initialization code. It is recommended to either put your sided event handler registration behind a <code>DistExecutor</code> call, or use the <code>@Mod.EventBusSubscriber</code> anntoation with '<code>value = Dist.CLIENT</code> for clients (or <code>value = Dist.DEDICATED_SERVER</code> for the dedicated server) to conditionally register your event handlers and prevent the classes referenced within from crashing upon being loaded. | | These events should be used for running side-specific initialization code. It is recommended to either put your sided event handler registration behind a <code>DistExecutor</code> call, or use the <code>@Mod.EventBusSubscriber</code> anntoation with '<code>value = Dist.CLIENT</code> for clients (or <code>value = Dist.DEDICATED_SERVER</code> for the dedicated server) to conditionally register your event handlers and prevent the classes referenced within from crashing upon being loaded. |
Line 64: |
Line 64: |
| === Reaching Across Logical Sides === | | === Reaching Across Logical Sides === |
| | | |
− | Whenever you want to send information from one logical side to another, you must '''always''' use network packets. It is incredibly tempting, when in a single player scenario, to directly transfer data from the logical server to the logical client. | + | Whenever you want to send information from one logical side to another, you must '''always''' use [[SimpleChannel|network packets]]. It is incredibly tempting, when in a single player scenario, to directly transfer data from the logical server to the logical client. |
| | | |
| This is actually very commonly inadvertently done through static fields. Since the logical client and logical server share the same JVM instance in a single player scenario, both threads writing to and reading from static fields will cause all sorts of race conditions and classical issues associated with threading. | | This is actually very commonly inadvertently done through static fields. Since the logical client and logical server share the same JVM instance in a single player scenario, both threads writing to and reading from static fields will cause all sorts of race conditions and classical issues associated with threading. |
Line 74: |
Line 74: |
| Your mods are expected to always load, regardless of if they are loaded on the client or the server. For one-sided mods, this means that they must still run on the opposite physical side. | | Your mods are expected to always load, regardless of if they are loaded on the client or the server. For one-sided mods, this means that they must still run on the opposite physical side. |
| | | |
− | So for one-sided mods, you would typically register your event handlers using [[#DistExecutor|<code>DistExecutor</code>]] or ''@EventBusSubscriber(value = Dist.*)'', instead of directly calling the relevant registration methods in the constructor. The idea is that, if your mod is loaded on the wrong side, it should simply do nothing: listen to no events, do no special behaviors, and so on. A one-sided mod by nature should not register blocks, items, … since they would need to be available on the other side, too. | + | So for one-sided mods, you would typically register your event handlers using [[#DistExecutor|<code>DistExecutor</code>]] or <code>@EventBusSubscriber(value = Dist.*)</code>, instead of directly calling the relevant registration methods in the constructor. The idea is that, if your mod is loaded on the wrong side, it should simply do nothing: listen to no events, do no special behaviors, and so on. A one-sided mod by nature should not register blocks, items, … since they would need to be available on the other side, too. |
| | | |
| Additionally, if your mod is one-sided, it typically does not forbid the user from joining a server that is lacking that mod, but the server menu will display the server as being incompatible (with a red <code>X</code> at the side). Therefore, you should override the <code>DISPLAYTEST</code> extension point to make sure that Forge does not think your mod is required on the server: (this is usually done in the mod constructor) | | Additionally, if your mod is one-sided, it typically does not forbid the user from joining a server that is lacking that mod, but the server menu will display the server as being incompatible (with a red <code>X</code> at the side). Therefore, you should override the <code>DISPLAYTEST</code> extension point to make sure that Forge does not think your mod is required on the server: (this is usually done in the mod constructor) |