Jump to content

Major Squirrel

Members
  • Posts

    117
  • Joined

  • Last visited

Converted

  • Gender
    Undisclosed
  • Personal Text
    Squirrel !

Major Squirrel's Achievements

Creeper Killer

Creeper Killer (4/8)

2

Reputation

  1. Good evening, According to some modders on Discord, the only way to use 22.5° degrees rotations properly in blockstates files would be to use OBJ models. Another solution would be to create 4 models with different rotations and to handle 4 different states per model in blockstates files so that it would handle the 16 rotations (see also this topic). Thank you for helping me !
  2. https://minecraft.gamepedia.com/Model#Block_states This is why I use the Forge blockstate format, with Forge marker set as 1. Well this is exactly what I did in my blockstates file : { "forge_marker": 1, "defaults": { "model": "mymod:standing_rp_sign", "uvlock": true }, "variants": { "rotation": { "0": { "transform": { "rotation": { "y": 180 } } }, "1": { "transform": { "rotation": { "y": 157.5 } } }, "2": { "transform": { "rotation": { "y": 135 } } }, "3": { "transform": { "rotation": { "y": 112.5 } } }, "4": { "transform": { "rotation": { "y": 90 } } }, "5": { "transform": { "rotation": { "y": 67.5 } } }, "6": { "transform": { "rotation": { "y": 45 } } }, "7": { "transform": { "rotation": { "y": 22.5 } } }, "8": { "transform": { "rotation": { "y": 0 } } }, "9": { "transform": { "rotation": { "y": 337.5 } } }, "10": { "transform": { "rotation": { "y": 315 } } }, "11": { "transform": { "rotation": { "y": 292.5 } } }, "12": { "transform": { "rotation": { "y": 270 } } }, "13": { "transform": { "rotation": { "y": 247.5 } } }, "14": { "transform": { "rotation": { "y": 225 } } }, "15": { "transform": { "rotation": { "y": 202.5 } } } } } } Following output :
  3. Well I don’t understand the behavior shown on my screenshot above. Did I do something wrong in my blockstate file ? I can’t figure out.
  4. I don't want to render any text on the sign, that is why I would like to avoid using TESR. According to @diesieben07 in the link I've posted above, the TRSRTransformation rotation can achieve 22.5 degrees increments, that's why I don't really understand.
  5. Thank you @desht, I will give a try. Also, I'm trying to avoid using TESR by only using Forge Blockstate format. For the wall sign it is pretty easy as Vanilla blockstate increments rotation every 90 degrees, but for the standing sign it is a little bit more complicated as it has 16 possible rotations. I've read this post where it is advised to use the Forge Blockstate V1 specs available here but I guess I have difficulties in understanding the specs. Here is what I got : The original model for the block (the uniform face is purposely complete beige so I could see where it faces) : (blockstates/standing_rp_sign.json) (block/standing_rp_sign.json) I don't really understand what is going on here tbh.
  6. The purpose would be to display data stored in the TileEntity, inside a GUI. Then, I guess I would call the server to retrieve the data and to pass it to the GUI ?
  7. (BlockRPSign.java) It works with the code above, I was overriding the wrong hasTileEntity method (the one without any parameter) , thank you. Could you please explain a little more about why you indicate me to use a proxy ? I know this part of code is executed on the server thread and I'm calling clientside code with Minecraft#displayGuiScreen, but I don't find a way to open a GUI remotely of a TileEntity without any Container. EDIT: is it as simple as using a GuiHandler and returning null in getServerGuiElement ...?
  8. I've added "empty" blockstate files and model files like so : (blockstates/standing_rp_sign.json) (blockstates/wall_rp_sign.json) (models/block/standing_rp_sign.json and models/block/wall_rp_sign.json) It does fix all MissingVariant exceptions as well as emitted particles when signs are destroyed. However, when changing my BlockRPSign from BlockContainer to Block with Block#hasTileEntity and Block#createTileEntity overriden, the render() method from the TESR is not called anymore. Instead, I've made my class extend to Block, implementing ITileEntityProvider. It works now. What do you mean by proxy ? Sending a packet to the server and the server opens a player GUI ?
  9. Good evening, Thank you @V0idWa1k3r for your answer. I couldn't find it in Vanilla code earlier. Is it in the BlockModelShapes#registerAllBlocks method ? I guess I will have to create an "empty" blockstates file if I want to override emitted particles anyway. Isn't this method supposed to be used when there is a Container attached to the TileEntity ? My TileEntity has no Container, it just has some data stored (TextComponents) in it. For what is left, I simply copied/pasted Vanilla code. Now I've fixed the useless casts, boxing/unboxing, arrays, etc... Thank you for that.
  10. Good evening, I'm modding a custom sign which is translucent and smaller than the Vanilla's one. I've looked for Vanilla classes to mimic the existing BlockSign and its children BlockStandingSign and BlockWallSign. I've also made a custom TileEntitySpecialRenderer and registered it. (BlockRPSign.java) (BlockStandingRPSign.java) (BlockWallRPSign.java) (ItemRPSign.java) (TileEntityRPSignRenderer.java) (MyModBlocks.java) (MyModItems.java) (MyModTileEntities.java) (As you may see, I'm using @jabelar mod structure from the GitHub repo here) I'm getting a net.minecraft.client.renderer.block.model.ModelBlockDefinition$MissingVariantException for my standing_rp_sign blockstate with rotation variants. I haven't created any blockstate file for both standing and wall signs since there is an existing TESR which handles the rendering. I've tried to look for a model loading from Vanilla's sign but I didn't find anything. My guess would be to indicate Forge to avoid handling models for those blocks but i don't know how to do that. Also, since there is no blockstate and no model attached to the blocks, there are random particles emitted when breaking the block. Vanilla sign has woods particles but I can't see any code or model file that indicates the texture to use for particles from Vanilla. Finally, as you can see in the TESR I'm trying to check the block type from the tileentity (this is done in Vanilla using Block#getBlockType which returns a Block). Is there a better way to do it ? Thank you for your help.
  11. Good evening, So as @Cadiboo stated above, I've been trying to avoid using an entity to render something above players head. The idea would be to send a CPacketPlayerTyping packet from the player typing to the server, then the server sends a SPacketNotifyTyping to every player around to render the indicator. (CPacketPlayerTyping.java) (SPacketNotifyTyping.java) (CustomGuiChat.java) (MyModMenu.java) I don't know what to do next in the onMessage function of the SPacketNotifyTyping packet. I've tried to call Gl functions but it is not in an OpenGL context. Also, I'm wondering if this is a good idea to send a packet on every screen update, what do you think ?
  12. I've updated the tracker accordingly, thank you. ? For now, it seems that it is working as intended (see screenshot below). I've tested it in singleplayer mode and I will test it in multiplayer mode later this day. You're right, I really don't need an entity. What I don't understand with your method is what should I do - on client side - after sending packets from server to client.
  13. My bad, I've created a new instance of EntityChatIndicator but completely forgot to spawn it in the world. The following code works : (ChatIndicatorMessage.java) @Override public IMessage onMessage(ChatIndicatorMessage message, MessageContext ctx) { EntityPlayerMP serverPlayer = ctx.getServerHandler().player; switch (message.messageType) { case 0: { serverPlayer.getServerWorld().addScheduledTask(() -> { Integer indicatorUniqueId = CHAT_INDICATORS.get(serverPlayer.getUniqueID()); if (indicatorUniqueId != null) { EntityChatIndicator chatIndicator = (EntityChatIndicator) serverPlayer.world.getEntityByID(indicatorUniqueId); if (chatIndicator != null) { chatIndicator.setDead(); CHAT_INDICATORS.remove(serverPlayer.getUniqueID()); } } }); break; } case 1: { serverPlayer.getServerWorld().addScheduledTask(() -> { EntityChatIndicator chatIndicator = new EntityChatIndicator(serverPlayer.world, serverPlayer.posX, serverPlayer.posY + 0.5D, serverPlayer.posZ); if (serverPlayer.world.spawnEntity(chatIndicator)) CHAT_INDICATORS.put(serverPlayer.getUniqueID(), chatIndicator.getEntityId()); }); break; } default: break; } return null; } I also modified updateFrequency from 0 to 20 because it causes a "/ by zero" exception. Now, entity updates functions are correctly called but still the doRender function is not called. Any guess ?
  14. Good evening, I've decided to go through an Entity for now, meaning that when a player opens a GuiChat, it sends a packet to the server and the server spawns an Entity with a custom Renderer to render the chat indicator above players head. Here is what I did so far : (ClientProxy.java) public class ClientProxy extends CommonProxy { @Override public void preInit() { super.preInit(); RenderingRegistry.registerEntityRenderingHandler(EntityChatIndicator.class, RenderFactoryEntityChatIndicator.INSTANCE); } @Override public void init() { super.init(); MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(new EntityEventHandler()); } @SubscribeEvent public void onOpenGui(GuiOpenEvent event) { if (event.getGui() != null) { if (event.getGui().getClass() == GuiChat.class) { event.setGui(new CustomGuiChat()); } } } } (CustomGuiChat.java) public class CustomGuiChat extends GuiChat { @Override public void initGui() { super.initGui(); MyModMenuPacketHandler.INSTANCE.sendToServer(new ChatIndicatorMessage(1)); } @Override public void onGuiClosed() { super.onGuiClosed(); MyModMenuPacketHandler.INSTANCE.sendToServer(new ChatIndicatorMessage(0)); } } (EntityEventHandler.java) @Mod.EventBusSubscriber(modid = MyModMenu.MODID) public final class EntityEventHandler { @SubscribeEvent public static void onEntityConstructing(EntityEvent.EntityConstructing event) { if (event.getEntity() instanceof EntityChatIndicator) { System.out.println("EntityChatIndicator is being constructed !"); } } @SubscribeEvent public static void onEntityRegistering(final RegistryEvent.Register<EntityEntry> event) { System.out.println("Registering entities..."); event.getRegistry().register(EntityEntryBuilder.create() .entity(EntityChatIndicator.class) .id(new ResourceLocation(MyModMenu.MODID, "chat_indicator"), 0) .name("chat_indicator") .tracker(0, 0, false) .build() ); } } (EntityChatIndicator.java) public class EntityChatIndicator extends Entity { public EntityChatIndicator(World worldIn) { this(worldIn, 0.0D, 0.0D, 0.0D); } public EntityChatIndicator(World worldIn, double posX, double posY, double posZ) { super(worldIn); this.setSize(1.0F, 1.0F); this.posX = posX; this.posY = posY; this.posZ = posZ; } @Override protected void entityInit() { } @Override public void onEntityUpdate() { super.onEntityUpdate(); System.out.println("EntityChatIndicator position : (" + this.posX + ", " + this.posY + ", " + this.posZ + ") !"); } @Override public void onUpdate() { super.onUpdate(); System.out.println("EntityChatIndicator position : (" + this.posX + ", " + this.posY + ", " + this.posZ + ") !"); } @Override protected void readEntityFromNBT(NBTTagCompound compound) {} @Override protected void writeEntityToNBT(NBTTagCompound compound) {} } (RenderChatIndicator.java) @SideOnly(Side.CLIENT) public final class RenderChatIndicator extends Render<EntityChatIndicator> { public RenderChatIndicator(RenderManager renderManager) { super(renderManager); } @Override public void doRender(EntityChatIndicator entity, double x, double y, double z, float entityYaw, float partialTicks) { System.out.println("Rendering EntityChatIndicator !"); ItemStack itemstack = new ItemStack(Items.PAPER, 1); if (!itemstack.isEmpty()) { GlStateManager.pushMatrix(); GlStateManager.translate(x, y, z); GlStateManager.rotate(-this.renderManager.playerViewY, 0, 1, 0); GlStateManager.rotate(this.renderManager.playerViewX, 1, 0, 0); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); Minecraft.getMinecraft().getRenderItem().renderItem(itemstack, ItemCameraTransforms.TransformType.GROUND); GlStateManager.popMatrix(); } super.doRender(entity, x, y, z, entityYaw, partialTicks); } @Nullable @Override protected ResourceLocation getEntityTexture(EntityChatIndicator entity) { return (null); } } (RenderFactoryChatIndicator.java) public class RenderFactoryEntityChatIndicator implements IRenderFactory<EntityChatIndicator> { public static final RenderFactoryEntityChatIndicator INSTANCE = new RenderFactoryEntityChatIndicator(); @Override public Render<EntityChatIndicator> createRenderFor(RenderManager manager) { return (new RenderChatIndicator(manager)); } } (MyModMenuPacketHandler.java) public final class MyModMenuPacketHandler { public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(MyModMenu.MODID); private static int discriminator = 0; public static <REQ extends IMessage, REPLY extends IMessage> void registerPacket(Class<? extends IMessageHandler<REQ, REPLY>> messageHandler, Class<REQ> message, Side side) { INSTANCE.registerMessage(messageHandler, message, MyModMenuPacketHandler.discriminator++, side); } } (ChatIndicatorMessage.java) public final class ChatIndicatorMessage implements IMessage { /** * First UUID key is player's UUID * Second Integer value is indicator's UUID */ public static final Map<UUID, Integer> CHAT_INDICATORS = new HashMap<>(); public ChatIndicatorMessage() {} /** * 0 is to DESTROY a chat indicator * 1 is to CREATE a chat indicator */ private int messageType; public ChatIndicatorMessage(int messageType) { this.messageType = messageType; } @Override public void fromBytes(ByteBuf buf) { this.messageType = buf.readInt(); } @Override public void toBytes(ByteBuf buf) { buf.writeInt(this.messageType); } public static final class ChatIndicatorMessageHandler implements IMessageHandler<ChatIndicatorMessage, IMessage> { @Override public IMessage onMessage(ChatIndicatorMessage message, MessageContext ctx) { EntityPlayerMP serverPlayer = ctx.getServerHandler().player; switch (message.messageType) { case 0: { serverPlayer.getServerWorld().addScheduledTask(() -> { Integer indicatorUniqueId = CHAT_INDICATORS.get(serverPlayer.getUniqueID()); if (indicatorUniqueId != null) { EntityChatIndicator chatIndicator = (EntityChatIndicator) serverPlayer.world.getEntityByID(indicatorUniqueId); if (chatIndicator != null) { chatIndicator.setDead(); CHAT_INDICATORS.remove(serverPlayer.getUniqueID()); } } }); break; } case 1: { serverPlayer.getServerWorld().addScheduledTask(() -> { EntityChatIndicator chatIndicator = new EntityChatIndicator(serverPlayer.world, serverPlayer.posX, serverPlayer.posY + 0.5D, serverPlayer.posZ); CHAT_INDICATORS.put(serverPlayer.getUniqueID(), chatIndicator.getEntityId()); }); break; } default: break; } return null; } } } (MyModMenu.java) @Mod(modid = MyModMenu.MODID, version = MyModMenu.VERSION) public class MyModMenu { public static final String MODID = "mymodmenu"; public static final String VERSION = "1.0.0"; @Mod.Instance public static MyModMenu instance; public static Logger logger; @SidedProxy(clientSide = "net.theviolentsquirrels.proxy.ClientProxy", serverSide = "net.theviolentsquirrels.proxy.ServerProxy") public static CommonProxy proxy; @EventHandler public void preInit(FMLPreInitializationEvent event) { MyModMenu.logger = event.getModLog(); MyModMenu.proxy.preInit(); MyModMenuPacketHandler.registerPacket(ChatIndicatorMessage.ChatIndicatorMessageHandler.class, ChatIndicatorMessage.class, Side.SERVER); } @EventHandler public void init(FMLInitializationEvent event) { MyModMenu.proxy.init(); } @EventHandler public void postInit(FMLPostInitializationEvent event) { } } So when I'm opening a GuiChat, it correctly prints out that a packet has been sent to the server. Also, it creates a new EntityChatIndicator (caught in the EntityConstructing event). However, the doRender function and the entity updates functions do not seem to be called at all (no print at least). What I've checked is : The packet is correctly registered The custom renderer seems to be correctly registered with the factory way The entity seems to be correctly registered with the recent builder I don't understand what is going on, maybe you could help me ? EDIT: is it because my EntityChatIndicator is simply an Entity, and not an EntityLiving ? Can a simple Entity be updated ?
  15. Good evening, I'm trying to develop a mod which renders a 2D texture above players to indicate other players that they're typing something in chat. AFAIK I would have to override the GuiChat to handle chat opening, update and chat closing & I would have to do something about rendering (I'm inspired by the way tags work above entities, is it the right way ?). I'm kind of confused right now because this is a client side part and I don't know how could I handle it to every player around the person typing in chat. Are packets the way to go ? Thank you for your replies.
×
×
  • Create New...

Important Information

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