TheGreyGhost
Members-
Posts
3280 -
Joined
-
Last visited
-
Days Won
8
Everything posted by TheGreyGhost
-
howdy Some of your method signatures weren't right and one of your imports (for Supplier) was wrong. The fixed classes (compiles fine now): /** * */ package genelectrovise.magiksmostevile.common.network.altar; import com.google.common.base.Optional; import genelectrovise.magiksmostevile.common.main.MagiksMostEvile; import net.minecraft.network.play.server.SWindowPropertyPacket; import net.minecraft.util.ResourceLocation; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.network.NetworkDirection; import net.minecraftforge.fml.network.NetworkRegistry; import net.minecraftforge.fml.network.simple.SimpleChannel; /** * @author GenElectrovise 23 May 2020 */ public class AltarNetworkingManager { public static SimpleChannel channel; public static final ResourceLocation channelRL = new ResourceLocation(MagiksMostEvile.MODID, "altar_channel"); public static final String MESSAGE_PROTOCOL_VERSION = "1.0"; public static final int ALTAR_ENERGY_TO_SERVER = 35; // a unique ID for this message type. It helps detect errors if you don't use // zero! public static final int ALTAR_ENERGY_TO_CLIENT = 63; @SubscribeEvent public static void onCommonSetupEvent(FMLCommonSetupEvent event) { channel = NetworkRegistry.newSimpleChannel(channelRL, () -> MESSAGE_PROTOCOL_VERSION, AltarMessageHandlerOnClient::isProtocolAccepted, AltarMessageHandlerOnServer::isProtocolAccepted); //channel.registerMessage(ALTAR_ENERGY_TO_SERVER, AltarEnergyUpdateMessageToServer.class, AltarEnergyUpdateMessageToServer::encode, AltarEnergyUpdateMessageToServer::decode, Optional.of(NetworkDirection.PLAY_TO_SERVER)); channel.registerMessage(ALTAR_ENERGY_TO_CLIENT, AltarEnergyUpdateMessageToClient.class, AltarEnergyUpdateMessageToClient::encode, AltarEnergyUpdateMessageToClient::decode, AltarMessageHandlerOnClient::onMessageReceived); } } /** * */ package genelectrovise.magiksmostevile.common.network.altar; import genelectrovise.magiksmostevile.common.main.MagiksMostEvile; import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.network.NetworkEvent; import java.util.function.Supplier; /** * @author GenElectrovise 24 May 2020 */ public class AltarMessageHandlerOnClient { /** * Called when a message is received of the appropriate type. CALLED BY THE * NETWORK THREAD, NOT THE CLIENT THREAD */ public static void onMessageReceived(final AltarEnergyUpdateMessageToClient message, Supplier<NetworkEvent.Context> ctxSupplier) { MagiksMostEvile.LOGGER.dev("Message recieved on client!"); ctxSupplier.get().setPacketHandled(true); if (!message.isValid()) { MagiksMostEvile.LOGGER.warn("Invalid message received on client."); return; } if (ctxSupplier.get().getDirection().getReceptionSide() != LogicalSide.CLIENT) { MagiksMostEvile.LOGGER.warn("Message recieved on incorrect side. (client) "); } // Creates a new task for the client for next tick ctxSupplier.get().enqueueWork(() -> processMessage(message)); } // This message is called from the Client thread. private static void processMessage(AltarEnergyUpdateMessageToClient message) { } public static boolean isProtocolAccepted(String protocolVersion) { return AltarNetworkingManager.MESSAGE_PROTOCOL_VERSION.equals(protocolVersion); } } /** * */ package genelectrovise.magiksmostevile.common.network.altar; import genelectrovise.magiksmostevile.common.main.MagiksMostEvile; import net.minecraft.network.PacketBuffer; /** * This Network Message is sent from the client to the server, to tell it to * spawn projectiles at a particular location. Typical usage: PREQUISITES: have * previously setup SimpleChannel, registered the message class and the * handler.<br> * <br> * * 1) User creates an AltarEnergyUpdateMessageToServer(targetCoordinates) <br> * 2) simpleChannel.sendToServer(airstrikeMessageToServer); <br> * 3) Forge network code calls message.encode() to copy the message member * variables to a PacketBuffer, ready for sending ... bytes are sent over the * network and arrive at the server.... <br> * 4) Forge network code calls message.decode() to recreate the * airstrickeMessageToServer instance by reading from the PacketBuffer into the * member variables <br> * 5) the handler.onMessage(message) is called to process the message * * @author GenElectrovise 24 May 2020 */ public class AltarEnergyUpdateMessageToClient { private static boolean messageIsValid; public AltarEnergyUpdateMessageToClient() { messageIsValid = true; } public boolean isMessageValid() { return messageIsValid; } /** * Called by the network code. Used to write the contents of your message member * variables into the ByteBuf, ready for transmission over the network. * * @param buf */ public void encode(PacketBuffer buf) { MagiksMostEvile.LOGGER.dev("Encoding message to client"); if (!messageIsValid) return; buf.writeString("example"); } /** * Called by the network code once it has received the message bytes over the * network. Used to read the ByteBuf contents into your member variables * * @param buf */ public static AltarEnergyUpdateMessageToClient decode(PacketBuffer buf) { MagiksMostEvile.LOGGER.dev("Decoding message to client"); return new AltarEnergyUpdateMessageToClient(); } public String toString() { return "AltarEnergyUpdateMessageToClient{TODO toString}"; } public boolean isValid() { return messageIsValid; } } Cheers -TGG
-
[SOLVED] Can't register Tile ( Forge 1.15.2 - 31.2.0 )
TheGreyGhost replied to BastouP's topic in Modder Support
Howdy. It seems to be a problem with using FMLJavaModLoadingContext.get().getModEventBus().addListener for your methods, it drops the generics information from the type signature. If you change your code to this instead (i.e. so that your methods are detected using @SubscribeEvent), it works fine. Probably some folks will tell you to use DeferredRegister instead, but @SubscribeEvent will also work perfectly well. -TGG package fr.bastoup.bperipherals; import fr.bastoup.bperipherals.init.ModBlocks; import fr.bastoup.bperipherals.init.ModItems; import fr.bastoup.bperipherals.init.ModTileTypes; import fr.bastoup.bperipherals.util.IHasModel; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.tileentity.TileEntityType; import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import fr.bastoup.bperipherals.util.BPeripheralsProperties; import net.minecraftforge.fml.common.Mod; @Mod(BPeripheralsProperties.MODID) public class BPeripherals { private static final Logger LOGGER = LogManager.getLogger(); // get a reference to the event bus for this mod; Registration events are fired on this bus. public static IEventBus MOD_EVENT_BUS; public BPeripherals() { // FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onItemRegister); // FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onBlockRegister); // FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onTileRegister); // FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onModelRegister); // MinecraftForge.EVENT_BUS.register(this); MOD_EVENT_BUS = FMLJavaModLoadingContext.get().getModEventBus(); MOD_EVENT_BUS.register(this); } @SubscribeEvent public void onItemRegister(final RegistryEvent.Register<Item> event) { event.getRegistry().registerAll(ModItems.ITEMS.toArray(new Item[0])); } @SubscribeEvent public void onBlockRegister(final RegistryEvent.Register<Block> event) { event.getRegistry().registerAll(ModBlocks.BLOCKS.toArray(new Block[0])); } @SubscribeEvent public void onTileRegister(final RegistryEvent.Register<TileEntityType<?>> event) { event.getRegistry().register( ModTileTypes.RF_METER ); } @SubscribeEvent public void onModelRegister(final ModelRegistryEvent event) { for (Item item : ModItems.ITEMS) { if(item instanceof IHasModel) { ((IHasModel) item).registerModels(); } } for (Block block : ModBlocks.BLOCKS) { if(block instanceof IHasModel) { ((IHasModel) block).registerModels(); } } } public static Logger getLogger() { return LOGGER; } } -
[SOLVED] Can't register Tile ( Forge 1.15.2 - 31.2.0 )
TheGreyGhost replied to BastouP's topic in Modder Support
Well I downloaded your code and ran it, and something strange is happening. your onTileRegister method is being given the Block Registry event for some reason public void onTileRegister(RegistryEvent.Register<TileEntityType<?>> event) { event.getRegistry().register( ModTileTypes.RF_METER ); } my debugger tells me that event is RegistryEvent.Register<minecraft:block> The same thing happens for RegistryEvent.Register<Item> event) as well. This part of Forge code is particularly difficult for me to understand because it's riddled with lambdas and the code commenting is non-existent, but I really think it should not do that. I'll keep digging and see if I can find out what's going on. -TGG -
Hi What are the symptoms, specifically? YOu might find this tutorial project useful, it has a working example of Particles (vanilla and custom) https://github.com/TheGreyGhost/MinecraftByExample/tree/master/src/main/java/minecraftbyexample/mbe50_particle -TGG
-
[SOLVED] Can't register Tile ( Forge 1.15.2 - 31.2.0 )
TheGreyGhost replied to BastouP's topic in Modder Support
hmm I'm guessing that your snipped code ... hides something like public void onTileRegister(RegistryEvent.Register<Block> event) { event.getRegistry().register( //line 45 ModTileTypes.RF_METER ); } i.e. the error isn't in the code that you showed us, it's in the Block register event instead -
Hi Yeah that's exactly how vanilla does it in many places (eg block mining); it executes the code logic on both client and server (eg eating to reduce fuel, gradual regeneration of stamina, etc), and periodically resynchs the client by sending it a packet. It will help a lot if you design your gameplay to be tolerant of mis-synch between client and server - for example, instead of making the player unable to swing at all below a certain stamina, you could make it always swing but just be very weak. That makes mis-synchronisation a lot less noticeable to the player than an on/off threshold (i.e. where the client thinks the player can swing but the server doesn't). -TGG
- 1 reply
-
- 1
-
Howdy I'm not sure what your mod is intended to do. Your block interacts with some sort of item (an item that it contains?) to read NBT from the item and display it? Something like a vanilla Anvil? You might find this example tutorial project useful; it has some working examples of tile entities (mbe20), reading/writing NBT for items (mbe12), and containers/tileentity (mbe30) https://github.com/TheGreyGhost/MinecraftByExample -TGG
-
Howdy Re the first part: I'm not sure what you're asking. Re the second part: search the vanilla code for MouseHelper.updatePlayerLook() and have a poke around to see how you might override it. -TGG
-
[SOLVED] Can't register Tile ( Forge 1.15.2 - 31.2.0 )
TheGreyGhost replied to BastouP's topic in Modder Support
Howdy you might find this example project useful https://github.com/TheGreyGhost/MinecraftByExample/tree/master/src/main/java/minecraftbyexample/mbe30_inventory_basic I suspect that in your case you have either mixed up your RF_METER objects (one is a block, the other is a TileEntity) or perhaps your public static final TileEntityType<?> RF_METER = TileEntityType.Builder. should be public static final TileEntityType<TileRFMeter> RF_METER = TileEntityType.Builder. -TGG -
Hi Your screen doesn't receive the packet information, the container (on the client side) does. The ContainerScreen asks the client container for the synchronised information. This all happens automatically if you use Slots and trackedInts; if you want to send other information then you need to register a packet-receiving method on the client side which writes the information into the client container. See SWindowPropertyPacket for how vanilla does it. In your case, it sounds like trackedInts should be fine for what you want to do. >I noticed that you're not using capabilities, but that shouldn't affect data synchronisation, should it? I haven't used those yet but no I don't think it should affect your screen synchronisation. -TGG
-
[1.15.2] How to create 3D item models with attachments?
TheGreyGhost replied to ken2020's topic in Modder Support
Howdy Items and Blocks use the same models (just lists of quads really) so the same code should work for both. You merge the models just by combining the list of quads i.e. this part @Override public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) { // our chess pieces are only drawn when side is NULL. if (side != null) { return parentModel.getQuads(state, side, rand); } List<BakedQuad> combinedQuadsList = new ArrayList(parentModel.getQuads(state, side, rand)); combinedQuadsList.addAll(getChessPiecesQuads(numberOfChessPieces)); return combinedQuadsList; } -TGG -
howdy What is happening is that your translucent quads are drawing to the depth buffer, so anything that is drawn afterwards is being hidden behind the translucent quads. Render order is important for translucent quads (alpha blending). You need to sort them so that the ones which are furthest away are drawn first. There is no OpenGL setting that will help you unfortunately. You can turn off translucent quads writing to the depth buffer but this has other side-effects. (Quads which are behind the translucent quads but are rendered afterwards will appear to be in front of the translucent quad). For blocks in 1.15.2, vanilla does the sorting for you, but your TileEntityRenderer needs to do it manually. You should also consider using render buffers instead the Tessellator. Are you using 1.15.2? https://gist.github.com/williewillus/30d7e3f775fe93c503bddf054ef3f93e -TGG
-
Howdy Synchronisation of GUI and TileEntity has some subtleties to be aware of. You might find this example tutorial useful (look at the parts related to trackedInts, used for fuel burn time). https://github.com/TheGreyGhost/MinecraftByExample/tree/master/src/main/java/minecraftbyexample/mbe31_inventory_furnace You can use custom packets instead, but it might be easier to use the vanilla synchronisation mechanism, even if your GUI doesn't need to use any item slots. -TGG
-
[1.15.2] How to create 3D item models with attachments?
TheGreyGhost replied to ken2020's topic in Modder Support
Howdy You might find this working example useful https://github.com/TheGreyGhost/MinecraftByExample/tree/master/src/main/java/minecraftbyexample/mbe15_item_dynamic_item_model It changes the appearance of the item depending on the item's properties. In your case, you could merge the model of the gun and the model of whichever scope you have attached to the gun (using NBT or a Capability). mbe04 also shows ways of combining two existing json models together. -TGG -
Howdy multipart blockstates are probably your best bet. Here's a working example of something very similar (a 3D web which joins itself to adjacent solid blocks) https://github.com/TheGreyGhost/MinecraftByExample/tree/master/src/main/java/minecraftbyexample/mbe03_block_variants -TGG
-
Howdy. You can detect the effects of players breaking a block on the client side, if they're within your render distance. That might be enough for you? Your client-side code could check the location of all players, every tick. And then you could look at the blocks within a reasonable radius of each player, to see if they have changed (been broken, TNT has been placed, etc). Might be better than nothing, if you have no way to install a mod on the server. -TGG
-
[1.15.2] World Render Transparency Issue
TheGreyGhost replied to nanorover59's topic in Modder Support
You could consider putting in a feature request to Forge to add an event at the appropriate place in updateCameraAndRender (or even better - fork the Forge source, add the event yourself, and submit a pull request). Or find another way to ensure that your code gets called at the right time; eg ensure that your miniworld is always associated with a TileEntity and TileEntityRenderer. Just a note - renderBlockLayer is called in several places, and you only need to ensure you have drawn before the call to the translucent renderBlockLayer, i.e. this one iprofiler.endStartSection("translucent"); this.renderBlockLayer(RenderType.getTranslucent(), matrixStackIn, d0, d1, d2); So you might have some success with DrawHighlightEvent for example -TGG -
Howdy You might find this working example useful https://github.com/TheGreyGhost/MinecraftByExample/tree/master/src/main/java/minecraftbyexample/mbe31_inventory_furnace It's also for a furnace, in 1.15.2 -TGG
-
[1.15.2] World Render Transparency Issue
TheGreyGhost replied to nanorover59's topic in Modder Support
Howdy Rendering of translucent objects is quite difficult because it is important to render the faces in the correct order. Normally, with opaque faces, it is straightforward because you can draw the faces in any order you like. When OpenGL draws a face, it checks the z-buffer to see whether the face is behind any other faces which are already in the scene. With translucent faces, this straight-forward approach doesn't work because the drawing order is important. Drawing face A then blending face B over the top of it gives a different appearance to drawing face B then blending face A over the top of B. For this reason, minecraft sorts translucent faces so that the ones which are furthest away are rendered first. You can see this by browsing through WorldRenderer::renderBlockLayer. I think (but haven't confirmed) that translucent faces still write to the depth buffer. It looks to me like, because you are rendering in last event which is after the translucent blocks have been rendered, your faces are being hidden behind the translucent faces, which have written to the depth buffer and will hence obscure anything that is behind them. This doesn't happen for some "transparent" textures like glass, because these use cutout textures not alpha blending. I.e. each pixel is either fully opaque, or fully transparent and doesn't write to the depth buffer. I don't know of an easy way to fix this, unfortunately. The most robust way to fix it is to render your blocks earlier, i.e. before renderBlockLayer is called in updateCameraAndRender. Perhaps a TileEntityRenderer might be the easiest way. -TGG -
Unknown Blockstate Property... But it's known
TheGreyGhost replied to Dubius's topic in Modder Support
Howdy I'd suggest you put a few breakpoints into the vanilla code as well as your Block's blockstate setup methods to see where the problem is. You could try using manual registration instead of Deferred in order to narrow it down eg @SubscribeEvent public static void onBlocksRegistration(final RegistryEvent.Register<Block> blockRegisterEvent) { -TGG -
Howdy > It could be, but what I'm asking is how would one make a texture that goes beyond the frame because the space it takes up is more than what a regular item takes up. I think you can achieve this using the gui display settings for the item model https://minecraft.gamepedia.com/Model under 'display'. If that doesn't do what you need, you can register a custom item renderer and render whatever you like. See Item.setISTER() -TGG
-
Howdy The open source Botania mod does something similar with Items (eg a bag that can hold items)- that may have some clues for you. Off the cuff, it sounds you may have a mismatch between client and server. It's not obvious in vanilla but when you open a container (eg for a chest), the container on the server is bound to the vanilla object (usually a tileentity) but the client container is not (in the case of a chest, for example, it's given a freshly-created (empty) IInventory instead of a TileEntity). The client container is synchronised with the server using the GUI slots packets. eg this diagram http://greyminecraftcoder.blogspot.com/2020/04/containers-1144.html -TGG
-
[1.15.2] Render TERs from RenderWorldLastEvent
TheGreyGhost replied to nanorover59's topic in Modder Support
Howdy. So which world do you pass to the TileEntity? The current world, or the inaccessible dimension? Perhaps your rendering is fine but the world offset is wrong, i.e. you think you're drawing at (say) [10, 135, 100] but it's actually rendering at [0,0,0] so you can't see it. You can test that by rendering very large quads or by moving to near [0,0,0] and trying modest offsets for your sub-world rendering, to see if you can spot where it's actually rendering. -TGG -
Hi Just use an item model json for your blockitem eg src/main/resources/assets/minecraftbyexample/models/item/mbe04b_block_altimeter_registry_name.json { "parent": "item/generated", "textures": { "layer0": "minecraftbyexample:item/mbe04b_altimeter_item_icon" } } where itemBlockAltimeter = new BlockItem(blockAltimeter, itemProperties); itemBlockAltimeter.setRegistryName(blockAltimeter.getRegistryName()); itemRegisterEvent.getRegistry().register(itemBlockAltimeter); -TGG