Jump to content

AnZaNaMa

Forge Modder
  • Posts

    161
  • Joined

  • Last visited

Converted

  • Gender
    Male
  • URL
    http://www.anzanama.com
  • Location
    Inside the ViewMatrix
  • Personal Text
    I only like Java, because I love Coffee

Recent Profile Visitors

4178 profile views

AnZaNaMa's Achievements

Creeper Killer

Creeper Killer (4/8)

3

Reputation

  1. Not sure if this is the right thread, so move it if I'm in the wrong place. I'm working on updating an old mod to 1.15.2, which runs a RESTful HTTP server alongside the game server that allows outside services to query information. Originally, I had implemented this using Netty, because it is already included in any Minecraft game. However, I was unable to figure out how to get an HTTPS server running, and honestly Netty is too low-level for this project. It required like 10 different classes just to get a basic HTTP server running. I've been looking into different libraries, and it seems like the Spring framework is something that would help me implement a RESTful API without having to re-invent the wheel 20 times first. However, I have no idea if it would even be possible to set up a mod with Spring, or how I would distribute it. Spring has tutorials on its site for setting it up with Gradle, but the sections of the build.gradle it's having me modify don't even exist in the ForgeGradle build.gradle Can anyone help me figure out how to set this up, or suggest a different networking library that has easy HTTP/HTTPS server support?
  2. Oh wow I'm stupid. Yeah, originally I was just using the normal block class. Guess I forgot to change it after I made my custom block class. I've changed it to TradeTerminalBlock and that's solved my problems. However, I still have a couple of questions. First off, it seems like the game is somehow saving my blockstate's properties when I quit the world, but I haven't written anything to translate the blockstate into nbt or metadata or anything. How is this information saved, since getStateFromMeta and getMetaFromState no longer exist? If I were to create my own custom BlockState property, would it also auto-magically be saved, or do I need to implement something to accomplish that? Also, do i need to manually send packets to the client when a blockstate changes, or is that handled by the game automatically? One more thing: Who's in charge of maintaining the Forge ReadTheDocs? I'd be willing to help contribute to update them if needed, since they're so out of date, but I don't know a ton.
  3. I checked out the Loom, because it uses HorizontalBlock Loom BlockState: { "variants": { "facing=north": { "model": "block/loom" }, "facing=south": { "model": "block/loom", "y": 180 }, "facing=west": { "model": "block/loom", "y": 270 }, "facing=east": { "model": "block/loom", "y": 90 } } } Loom Model: { "parent": "block/orientable", "textures": { "top": "block/loom_top", "bottom": "block/loom_bottom", "front": "block/loom_front", "side": "block/loom_side" } } As you can see, my blockstate is almost exactly the same as what's used in Vanilla, but for some reason, minecraft still isn't recognizing the BlockState property. Do I need to register my block to tell the game it uses that property somehow? I've implemented fillStateContainer, getStateForPlacement, and I set the default state in my constructor.
  4. Hello, I'm having some troubles getting simple BlockStates to work in 1.15.2 (forge 31.1.1). Currently, I'm trying to get a simple rotatable block. Originally, I tried using the official Forge ReadTheDocs, but I've noticed that the Forge documentation is SEVERAL MAJOR VERSIONS out of date. The readthedocs says that the documentation is for 1.15.x, but most of the information in there is clearly out of date. All of the references it makes use the old naming scheme, and it often tells you to use methods that no longer exist. I was following the instructions on the docs, but that tutorial says you have to implement getMetaFromState and getStateFromMeta, which are methods that don't exist in this version. I found Cabidoo's 1.15.2 example mod repository, so I've been trying to follow what they've done there with their ModFurnaceBlock. For some reason when the game loads, I get errors saying that 'facing' is an unknown blockstate property, even though it's one of the built-in ones. [22:48:40] [Server-Worker-2/WARN] [minecraft/ModelBakery]: Exception loading blockstate definition: 'smartshops:blockstates/trade_terminal.json' in resourcepack: 'Mod Resources' for variant: 'facing=south': Unknown blockstate property: 'facing' [22:48:40] [Server-Worker-2/WARN] [minecraft/ModelBakery]: Exception loading blockstate definition: 'smartshops:blockstates/trade_terminal.json' in resourcepack: 'Mod Resources' for variant: 'facing=east': Unknown blockstate property: 'facing' [22:48:40] [Server-Worker-2/WARN] [minecraft/ModelBakery]: Exception loading blockstate definition: 'smartshops:blockstates/trade_terminal.json' in resourcepack: 'Mod Resources' for variant: 'facing=north': Unknown blockstate property: 'facing' [22:48:40] [Server-Worker-2/WARN] [minecraft/ModelBakery]: Exception loading blockstate definition: 'smartshops:blockstates/trade_terminal.json' in resourcepack: 'Mod Resources' for variant: 'facing=west': Unknown blockstate property: 'facing' [22:48:40] [Server-Worker-2/WARN] [minecraft/ModelBakery]: Exception loading blockstate definition: 'smartshops:blockstates/trade_terminal.json' missing model for variant: 'smartshops:trade_terminal#' I'm assuming the last message is only a problem because the BlockState variants failed to load properly. Also, the texture shows up as a full cube with the purple and black missing texture in game. Here are the relevant files to my problem: TradeTerminalBlock, trade_terminal.json (blockstate file), trade_terminal.json (model file). Also, is there an updated version of the documentation anywhere, or even just a set of update notes, telling what's changed since whenever the last time the docs were updated was?
  5. Hello! I've noticed that newer versions of Forge like to dump out the entire registry when the game loads, which makes it annoying to try and read through the console while testing mods in my development environment. Is there a way to disable this registry dump, while still keeping the log level at DEBUG?
  6. I managed to figure it out. I had my @EventBusSubscriber wrong (had to subscribe to the client-specific bus for the FMLCommonSetupEvent). Because of that, the event handler wasn't firing, so the instance of the capability was never being injected with a value, so it was still null when I tried to use it. @Draco18s also, you were right. I was just passing an instance of my ILifeForce, when I needed to pass it a supplier. I ended up using a lambda supplier: @SubscribeEvent public static void onCommonSetupEvent(FMLCommonSetupEvent event) { CapabilityManager.INSTANCE.register(ILifeForce.class, new LifeForceStorage(), () -> new LifeForce()); }
  7. LIFE_FORCE_CAP is a Capability<ILifeForce>, so the call to LIFE_FORCE_CAP::getDefaultInstance will resolve to Capability::getDefaultInstance which does exist. I was under the impression that getDefultInstance would return the instance of LifeForce that I passed into CapabilityManager.INSTANCE.register()
  8. FIrst off, the file contents you gave for your model file for example_item.json look like a localization file. For regular rendering of an item, your src\main\resources\assets\fm\models\item\example_item.json would look something like this: { "parent": "item/generated", "textures": { "layer0": "modid:item/example_item" } } That "modid:item/example_item" is a resource location for the texture that will be used to draw layer0, which is the only layer in this case. Essentially, the "modid:item/example_item" refers to the texture for your item. With the way that resource locations work, your actual texture for the item should be located at src\main\resources\assets\fm\textures\item\example_item.png, rather than in the models folder. Also, I think you'll want to put that localization information in the file: src\main\resources\assets\fm\lang\en_us.json Edit: I feel like I should explain more. The "resources\assets\modid\models" folder contains files that describe the way an object in the game should look. Unless you're using more complicated rendering techniques, these files are in the form of .json files (which is part of a system that resulted from the changes made in 1.8). These models make references to the textures that will be used to draw items/blocks. The textures themselves (.png images) will be searched for in the "resources\assets\modid\textures" folder. You can find more information on models in the Forge Docs.
  9. Hello, I'm working on implementing a capability for living entities for a mod I'm working on and I've run into some trouble. I believe I've gotten most of it right, from what I've gathered from other threads here. The trouble I'm running into is when the AttachCapabilitiesEvent<Entity> I'm hooking into fires. When that event fires, I'm calling event.addCapability(), and the game crashes while it's attempting to create the new instance of my capability provider (ICapabilitySerializable), throwing a null pointer exception. Here, you can see my event listener for the AttachCapabilitiesEvent<Entity>, as well as the registration for my capability: @SubscribeEvent public static void onCommonSetup(FMLCommonSetupEvent event) { CapabilityManager.INSTANCE.register(ILifeForce.class, new LifeForceStorage(), LifeForce::new); } @SubscribeEvent public static void onAttachCapabilities(AttachCapabilitiesEvent<Entity> event) { if(event.getObject() instanceof LivingEntity) { event.addCapability(new ResourceLocation(LifePower.MODID, "lifeforce"), new LifeForceProvider()); event.getObject().getCapability(LifeForceProvider.LIFE_FORCE_CAP).ifPresent((capability) -> { capability.set(Math.round(((LivingEntity) event.getObject()).getHealth())); }); } } Here's the gist of the crash report: Description: Ticking memory connection java.lang.NullPointerException: Ticking memory connection at com.networkoverflow.lifepower.content.capabilities.LifeForceProvider.<init>(LifeForceProvider.java:14) ~[classes/:?] {pl:capability_inject_definalize:A} at com.networkoverflow.lifepower.content.capabilities.CapabilityHandler.onAttachCapabilities(CapabilityHandler.java:25) ~[classes/:?] {} at net.minecraftforge.eventbus.ASMEventHandler_0_CapabilityHandler_onAttachCapabilities_AttachCapabilitiesEvent.invoke(.dynamic) ~[?:?] {} (Full Crash Report) Here is my LifeForceProvider.java (with line 14, the crash line, marked): package com.networkoverflow.lifepower.content.capabilities; import net.minecraft.nbt.INBT; import net.minecraft.util.Direction; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.common.util.LazyOptional; public class LifeForceProvider implements ICapabilitySerializable<INBT> { @CapabilityInject(ILifeForce.class) public static final Capability<ILifeForce> LIFE_FORCE_CAP = null; private LazyOptional<ILifeForce> instance = LazyOptional.of(LIFE_FORCE_CAP::getDefaultInstance); //THIS IS WHAT CRASHES <----- @Override public <T> LazyOptional<T> getCapability(Capability<T> capability, Direction direction) { return capability == LIFE_FORCE_CAP ? instance.cast() : LazyOptional.empty(); } @Override public INBT serializeNBT() { return LIFE_FORCE_CAP.getStorage().writeNBT(LIFE_FORCE_CAP, this.instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null); } @Override public void deserializeNBT(INBT nbt) { LIFE_FORCE_CAP.getStorage().readNBT(LIFE_FORCE_CAP, this.instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null, nbt); } } So, as you can see, the LazyOptional.of() that I'm calling is raising a NullPointerException, which I think refers to LIFE_FORCE_CAP being null. However, I thought that because that variable has the @CapabilityInject annotation, its null value would be replaced with whatever forge generates. One reason I could think of for this happening is if I'm hooking into the wrong place to register my capability. In this thread, @Animefan8888 mentioned that the call to CapabilityManager.INSTANCE.register() should happen in the FMLCommonSetupEvent. Is this the wrong place to register my capability, or am I doing something else wrong? All code related to this capability
  10. Hello, I'm working on a mod that communicates information about the minecraft server to outside sources. One of the ways I'm trying to accomplish this is by hooking into certain events and sending out an HTTP post request with a json payload to a user-defined endpoint. I'm using Netty to accomplish this, since it's already used by minecraft. For some reason, though, my HttpClient won't send the messages through. I have print statements before and after message sending and it gets to the first message, but never gets to the second one. I realize this is more of a question about Netty than forge but the Netty community doesn't seem to be very active and I haven't gotten a response yet. I'm hoping that someone here will be able to help me with this issue. Below, you can find my code: package com.anzanama.statusapi.http.client; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.*; import io.netty.util.CharsetUtil; public class HttpClient { private String uri; private int port; private String payload; public HttpClient(String uri, int port, String payload) { this.uri = uri; this.port = port; this.payload = payload; } public void run() throws Exception { EventLoopGroup workerGroup = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); //b.option(ChannelOption.SO_KEEPALIVE, true); b.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new HttpClientCodec()); ch.pipeline().addLast(new HttpObjectAggregator(1048576)); ch.pipeline().addLast(new HttpClientHandler()); ch.pipeline().addLast(new HttpRequestEncoder()); } }); HttpRequest request = HttpRequester.createRequest(this.uri, this.payload); request.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json"); System.out.println("Sending message!"); Channel f = b.connect(uri, port).channel(); f.writeAndFlush(request); f.closeFuture().sync(); System.out.println("Message was sent!"); } finally { workerGroup.shutdownGracefully(); } } } package com.anzanama.statusapi.http.client; import io.netty.handler.codec.http.*; import static io.netty.buffer.Unpooled.copiedBuffer; public class HttpRequester { public static FullHttpRequest createRequest(String uri, String payload) { return createRequest(uri, payload.getBytes()); } public static FullHttpRequest createRequest(String uri, byte[] payload) { return createRequest(uri, payload, HttpVersion.HTTP_1_1); } public static FullHttpRequest createRequest(String uri, byte[] payload, final HttpVersion version) { if (0 < payload.length) { FullHttpRequest request = new DefaultFullHttpRequest(version, HttpMethod.POST, uri, copiedBuffer(payload)); request.headers().set(HttpHeaderNames.CONTENT_LENGTH, payload.length); return request; } else { return new DefaultFullHttpRequest(version, HttpMethod.POST, uri); } } }
  11. I discovered that either minecraft or forge is already keeping a record of tick times, so I'll just use this instead to avoid having a tick handler that bogs down the server. For anyone in the future, who's interested in this, look in net.minecraftforge.server.command.CommandTps to see how the forge TPS command calculates it.
  12. Hello, I'm attempting to monitor the average tick time of a forge server in my mod. Currently, I'm using an event handler that subscibes to TickEvent.ServerTickEvent to record System.currentTimeMillis each tick and then when someone asks for the TPS, I average out the differences between times in the array to find the mean tick time in milliseconds and divide 1000 by that to get the TPS. However, the numbers I come up with are always much larger than those produced by the 'forge tps' command (i.e. 0.3ms vs 10ms). I'm fairly certain my math is correct, which means there must be a problem with the way I am recording data each tick. Is there a better way for me to accomplish this? Below is my code: @SubscribeEvent public static void onTick(TickEvent.ServerTickEvent event) { StatusAPI.data.tick(); } public static JsonObject tps() { long[] tickList = StatusAPI.data.getTickList(); long totalMillis = 0; int endIndex = tickList[tickList.length-1] != 0 ? tickList.length : StatusAPI.data.getTickListIndex(); for(int i=0; i < endIndex - 1; i++) { long diff = tickList[i+1] - tickList[i]; totalMillis += diff; } float averageMillis = (float)totalMillis / (float)endIndex; float ticksPerSecond = 1000F / averageMillis; JsonObject data = new JsonObject(); DecimalFormat df = new DecimalFormat("0.00"); data.addProperty("ticksPerSecond", df.format(ticksPerSecond)); data.addProperty("averageTickTime", df.format(averageMillis)); return data; }
  13. I have a command that teleports a player to another player and in that, I make a check to see if the player is in the same dimension as the other one, and if not, I call EntityPlayer::changeDimension(); This seems to teleport the player fine, but it causes a weird desync with the client. The mod is server side only, as it's only a commands mod and I don't want to make my players have to download anything additional. The client acts like it doesn't know it moved to a new dimension. It sees everything in the new dimension fine, but other players can't see the one who teleported and the client has to relog into the server to be able to see items they dropped. I assume I need to send the client some sort of update packet, but I can't find anything in EntityPlayer for updating beside the EntityPlayer::sendPlayerAbilities() which wouldn't do what I want. Any tips?
  14. Thank you. Sorry, I haven't worked with entities so I didn't have any experience with methods involving them or I would have just looked there.
×
×
  • Create New...

Important Information

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