Popular New Releases in Minecraft
byte-buddy
Byte Buddy 1.12.8
mumble
1.3.4
docker-minecraft-server
2022.6.0
baritone
v1.8.1
HMCL
v3.5.2.218
Popular Libraries in Minecraft
by fogleman c
8642 MIT
A simple Minecraft clone written in C using modern OpenGL (shaders).
by PaperMC java
5799 NOASSERTION
High performance Spigot fork that aims to fix gameplay and mechanics inconsistencies
by MinecraftForge java
5407 NOASSERTION
Modifications to the Minecraft base files to assist in compatibility between mods.
by raphw java
4838 Apache-2.0
Runtime code generation for the Java virtual machine.
by fogleman python
4622 MIT
Simple Minecraft-inspired program using Python and Pyglet
by mumble-voip c++
4481 NOASSERTION
Mumble is an open-source, low-latency, high quality voice chat software.
by itzg shell
4378 Apache-2.0
Docker image that provides a Minecraft Server that will automatically download selected version at startup
by cuberite c++
4060 NOASSERTION
A lightweight, fast and extensible game server for Minecraft
by cabaletta java
4053 NOASSERTION
google maps for block game
Trending New libraries in Minecraft
by CaffeineMC java
3168 LGPL-3.0
A Fabric mod designed to improve frame rates and reduce micro-stutter
by PojavLauncherTeam java
2537 GPL-3.0
A Minecraft: Java Edition Launcher for Android and iOS based on Boardwalk. This repository contains source code for Android platform.
by IrisShaders java
2036 LGPL-3.0
(WIP) A modern shaders mod for Minecraft intended to be compatible with existing OptiFine shader packs
by jdah c
1967 MIT
Minecraft, but I made it in 48 hours.
by doctorray117 typescript
1234 Apache-2.0
Templates to deploy a serverless Minecraft Server on demand in AWS
by sm64pc c
1078
Fork of https://github.com/sm64-port/sm64-port with additional features.
by PorkStudios java
1065 NOASSERTION
Level-of-Detail renderer in Minecraft. Allows for render distances of millions of blocks. (Cubic Chunks-compatible) (WIP)
by michaljaz javascript
941 MIT
Minecraft client written in Javascript
by AOF-Dev java
923 NOASSERTION
MCinaBox - A Minecraft: Java Edition Launcher for Android. An Encapsulation of [CosineMath's BoatApp](https://github.com/AOF-Dev/BoatApp).
Top Authors in Minecraft
1
40 Libraries
5314
2
33 Libraries
224
3
25 Libraries
453
4
25 Libraries
135
5
23 Libraries
158
6
23 Libraries
167
7
22 Libraries
315
8
22 Libraries
1081
9
22 Libraries
733
10
21 Libraries
338
1
40 Libraries
5314
2
33 Libraries
224
3
25 Libraries
453
4
25 Libraries
135
5
23 Libraries
158
6
23 Libraries
167
7
22 Libraries
315
8
22 Libraries
1081
9
22 Libraries
733
10
21 Libraries
338
Trending Kits in Minecraft
No Trending Kits are available at this moment for Minecraft
Trending Discussions on Minecraft
First-person controller y-pos logic in Ursina
How to configure slf4j (for JDA) to work with log4j (for Minecraft Paper)?
Error [ERR_REQUIRE_ESM]: require() of ES Module not supported
Log4j vulnerability - Is Log4j 1.2.17 vulnerable (was unable to find any JNDI code in source)?
Minecraft Plugin ClassNotFound Error from External JAR
Infer dependencies in Gradle subproject from its parent project
Minecraft Forge 1.7.10 Custom Entity Not Spawning On The Client?
Generate custom ores in custom dimension
Special condition - remove all the version numbers from the mods to search for the new version
How to filter an array on click in react?
QUESTION
First-person controller y-pos logic in Ursina
Asked 2022-Mar-15 at 07:04I have a clone of Minecraft and I want to see if the player falls off the island it would quit the game. I thought that if I wrote.
1if player.position == Vec3(x, -80, z):
2 quit()
3
it would quit the game but that didn't work so I don't know what to do.
Heres the Minecraft clone code.
1if player.position == Vec3(x, -80, z):
2 quit()
3from ursina import *
4from ursina.prefabs.first_person_controller import FirstPersonController
5app = Ursina()
6
7grass_color = color.rgb(1, 235, 113)
8stone_color = color.rgb(138,141,143)
9dirt_color = color.rgb(200, 157, 124)
10
11block_pick = 1
12
13def update():
14 if held_keys['escape']:
15 quit()
16
17 global block_pick
18
19 if held_keys['1']: block_pick = 1
20 if held_keys['2']: block_pick = 2
21 if held_keys['3']: block_pick = 3
22
23class Voxel(Button):
24 def __init__(self, position = (0,0,0), color = color.white):
25 super().__init__(
26 parent = scene,
27 position = position,
28 model = 'cube',
29 origin_y = 0.5,
30 texture = 'white_cube',
31 color = color,
32 highlight_color = color,
33 )
34
35 def input(self,key):
36 if self.hovered:
37 if key == 'right mouse down':
38 if block_pick == 1:voxel = Voxel(position = self.position + mouse.normal, color = grass_color)
39 if block_pick == 2:voxel = Voxel(position = self.position + mouse.normal, color = stone_color)
40 if block_pick == 3:voxel = Voxel(position = self.position + mouse.normal, color = dirt_color)
41 if key == 'left mouse down':
42 destroy(self)
43
44for z in range(20):
45 for x in range(20):
46 voxel = Voxel(position=(x,0,z), color = grass_color)
47
48for y in range(3):
49 for x in range(20):
50 for z in range(20):
51 voxel = Voxel(position=(x,y + -3,z), color = dirt_color)
52
53player = FirstPersonController()
54app.run()
55
ANSWER
Answered 2022-Mar-15 at 07:04You checked only for a single value of the player's y position which won't work - after all, you'd be falling down quickly. You could check whether the player's height is below a certain cutoff:
1if player.position == Vec3(x, -80, z):
2 quit()
3from ursina import *
4from ursina.prefabs.first_person_controller import FirstPersonController
5app = Ursina()
6
7grass_color = color.rgb(1, 235, 113)
8stone_color = color.rgb(138,141,143)
9dirt_color = color.rgb(200, 157, 124)
10
11block_pick = 1
12
13def update():
14 if held_keys['escape']:
15 quit()
16
17 global block_pick
18
19 if held_keys['1']: block_pick = 1
20 if held_keys['2']: block_pick = 2
21 if held_keys['3']: block_pick = 3
22
23class Voxel(Button):
24 def __init__(self, position = (0,0,0), color = color.white):
25 super().__init__(
26 parent = scene,
27 position = position,
28 model = 'cube',
29 origin_y = 0.5,
30 texture = 'white_cube',
31 color = color,
32 highlight_color = color,
33 )
34
35 def input(self,key):
36 if self.hovered:
37 if key == 'right mouse down':
38 if block_pick == 1:voxel = Voxel(position = self.position + mouse.normal, color = grass_color)
39 if block_pick == 2:voxel = Voxel(position = self.position + mouse.normal, color = stone_color)
40 if block_pick == 3:voxel = Voxel(position = self.position + mouse.normal, color = dirt_color)
41 if key == 'left mouse down':
42 destroy(self)
43
44for z in range(20):
45 for x in range(20):
46 voxel = Voxel(position=(x,0,z), color = grass_color)
47
48for y in range(3):
49 for x in range(20):
50 for z in range(20):
51 voxel = Voxel(position=(x,y + -3,z), color = dirt_color)
52
53player = FirstPersonController()
54app.run()
55def update():
56 if player.y < -80:
57 print('You fell to death!')
58 app.quit()
59
QUESTION
How to configure slf4j (for JDA) to work with log4j (for Minecraft Paper)?
Asked 2022-Mar-11 at 16:05I'm making plugin for Minecraft - 'Paper' exactly. And it uses JDA for Discord bot function.
The problem is, Minecraft(Paper) uses log4j as its logging library. JDA uses slf4j as its logging library. I want JDA to use log4j so that error message of JDA would be shown in console as plugin's error message. (See EDIT2 for actual logs)
No System.out.println()
because Minecraft(Paper) will complain about using it.
No Logback because I think it is another logging library, thus it cannot work well with Minecraft(Paper)'s logging system (no JDA logs in Minecraft log etc.). I don't want to implement another logging library when there is already logging system provided by Minecraft, which is log4j.
JDA wiki only describes about Logback so I have to find my own way for making JDA with Minecraft's logging system, but it was no success.
For example:
1// Something went wrong in JDA and shows stacktrace
2[05:20:26] [Server thread/ERROR]: [MyPlugin] [JDA] 'JDA Error Message'
3(prints stacktrace of the error)
4
5// Show debug message of WebSocketClient (Since it is debug message, this can be turned off)
6[05:20:26] [Server thread/DEBUG]: [MyPlugin] [JDA] WebSocketClient - Connected to WebSocket
7
8// Show JDA message when JDA bot is loaded
9[05:20:26] [Server thread/DEBUG]: [MyPlugin] [JDA] JDA - Finished Loading!
10
These all messages should be part of the Minecraft(Paper)'s logging system, not mimicing it. This means, it should use JavaPlugin#getLogger().info()
or something like this in somewhere of the code.
How to make JDA to be like this?
Just implementing log4j-slf4j18-impl
doesn't work. I think I should do something about JDA's logging stuff.
EDIT: Here is current build.gradle
file content. LINK
Currently, my plugin implements log4j-slf4j-impl
for JDA.
ANSWER
Answered 2022-Feb-27 at 07:57Log4j 2 SLF4J Binding exists for that purpose.
It is an SLF4J logger implementation (like slf4j-simple
) that logs everything to log4j. In other words, everything logged with SLF4J will be forwarded to log4j.
In order to use it, just add the following to your pom.xml
(see this):
1// Something went wrong in JDA and shows stacktrace
2[05:20:26] [Server thread/ERROR]: [MyPlugin] [JDA] 'JDA Error Message'
3(prints stacktrace of the error)
4
5// Show debug message of WebSocketClient (Since it is debug message, this can be turned off)
6[05:20:26] [Server thread/DEBUG]: [MyPlugin] [JDA] WebSocketClient - Connected to WebSocket
7
8// Show JDA message when JDA bot is loaded
9[05:20:26] [Server thread/DEBUG]: [MyPlugin] [JDA] JDA - Finished Loading!
10<dependency>
11 <groupId>org.apache.logging.log4j</groupId>
12 <artifactId>log4j-slf4j18-impl</artifactId>
13 <version>2.17.2</version>
14</dependency>
15
If you use Gradle, it would look like this:
1// Something went wrong in JDA and shows stacktrace
2[05:20:26] [Server thread/ERROR]: [MyPlugin] [JDA] 'JDA Error Message'
3(prints stacktrace of the error)
4
5// Show debug message of WebSocketClient (Since it is debug message, this can be turned off)
6[05:20:26] [Server thread/DEBUG]: [MyPlugin] [JDA] WebSocketClient - Connected to WebSocket
7
8// Show JDA message when JDA bot is loaded
9[05:20:26] [Server thread/DEBUG]: [MyPlugin] [JDA] JDA - Finished Loading!
10<dependency>
11 <groupId>org.apache.logging.log4j</groupId>
12 <artifactId>log4j-slf4j18-impl</artifactId>
13 <version>2.17.2</version>
14</dependency>
15compile 'org.apache.logging.log4j:log4j-slf4j18-impl:2.17.2'
16
Adding this dependency includes and automatically registers the logger.
QUESTION
Error [ERR_REQUIRE_ESM]: require() of ES Module not supported
Asked 2022-Feb-03 at 22:08I'm trying to make a Discord bot that just says if someone is online on the game.
However I keep getting this message:
[ERR_REQUIRE_ESM]: require() of ES Module from not supported. Instead change the require of index.js in... to a dynamic import() which is available in all CommonJS modules.
This is my code:
1 module.exports = {
2 name: 'username',
3 description: "this is the username command",
4 async execute(message, args) {
5
6 const fetch = require('node-fetch');
7
8 if (args.length !== 1) {
9 return message.channel.send("invalid username wtf")
10 }
11
12 const ign = args[0]
13
14 if (ign.length > 16 || ign.length < 3) {
15 return message.channel.send("invalid username wtf")
16 }
17
18 const uuid = await fetch(`https://api.mojang.com/users/profiles/minecraft/${ign}`).then(data => data.json()).then(data => data.id).catch(err => message.channel.send("error wtf"));
19 const onlineInfo = await fetch(`https://api.hypixel.net/status?key=${john}&uuid=${uuid}`).then(data => data.json());
20
21 if (uuid.length !== 32) {
22 return;
23 }
24
25 if (onlineinfo.success) {
26 if (onlineinfo.session.online) {
27 message.channel.send("they are online")
28 }
29 else {
30 message.channel.send("they are offline")
31 }
32 }
33 else {
34 message.channel.send("hypixel api bad wtf")
35 }
36 }
37 }
38
This is my package.json file:
1 module.exports = {
2 name: 'username',
3 description: "this is the username command",
4 async execute(message, args) {
5
6 const fetch = require('node-fetch');
7
8 if (args.length !== 1) {
9 return message.channel.send("invalid username wtf")
10 }
11
12 const ign = args[0]
13
14 if (ign.length > 16 || ign.length < 3) {
15 return message.channel.send("invalid username wtf")
16 }
17
18 const uuid = await fetch(`https://api.mojang.com/users/profiles/minecraft/${ign}`).then(data => data.json()).then(data => data.id).catch(err => message.channel.send("error wtf"));
19 const onlineInfo = await fetch(`https://api.hypixel.net/status?key=${john}&uuid=${uuid}`).then(data => data.json());
20
21 if (uuid.length !== 32) {
22 return;
23 }
24
25 if (onlineinfo.success) {
26 if (onlineinfo.session.online) {
27 message.channel.send("they are online")
28 }
29 else {
30 message.channel.send("they are offline")
31 }
32 }
33 else {
34 message.channel.send("hypixel api bad wtf")
35 }
36 }
37 }
38{
39 "name": "discordbot",
40 "version": "1.0.0",
41 "main": "main.js",
42 "scripts": {
43 "test": "echo \"Error: no test specified\" && exit 1",
44 "start": "node main.js"
45 },
46 "author": "",
47 "license": "ISC",
48 "description": "",
49 "dependencies": {
50 "discord.js": "^13.0.1",
51 "node-fetch": "^3.0.0"
52 }
53}
54
ANSWER
Answered 2021-Sep-07 at 06:38node-fetch
v3 recently stopped support for the require
way of importing it in favor of ES Modules. You'll need to use ESM imports now, like:
1 module.exports = {
2 name: 'username',
3 description: "this is the username command",
4 async execute(message, args) {
5
6 const fetch = require('node-fetch');
7
8 if (args.length !== 1) {
9 return message.channel.send("invalid username wtf")
10 }
11
12 const ign = args[0]
13
14 if (ign.length > 16 || ign.length < 3) {
15 return message.channel.send("invalid username wtf")
16 }
17
18 const uuid = await fetch(`https://api.mojang.com/users/profiles/minecraft/${ign}`).then(data => data.json()).then(data => data.id).catch(err => message.channel.send("error wtf"));
19 const onlineInfo = await fetch(`https://api.hypixel.net/status?key=${john}&uuid=${uuid}`).then(data => data.json());
20
21 if (uuid.length !== 32) {
22 return;
23 }
24
25 if (onlineinfo.success) {
26 if (onlineinfo.session.online) {
27 message.channel.send("they are online")
28 }
29 else {
30 message.channel.send("they are offline")
31 }
32 }
33 else {
34 message.channel.send("hypixel api bad wtf")
35 }
36 }
37 }
38{
39 "name": "discordbot",
40 "version": "1.0.0",
41 "main": "main.js",
42 "scripts": {
43 "test": "echo \"Error: no test specified\" && exit 1",
44 "start": "node main.js"
45 },
46 "author": "",
47 "license": "ISC",
48 "description": "",
49 "dependencies": {
50 "discord.js": "^13.0.1",
51 "node-fetch": "^3.0.0"
52 }
53}
54import fetch from "node-fetch";
55
at the top of your file.
QUESTION
Log4j vulnerability - Is Log4j 1.2.17 vulnerable (was unable to find any JNDI code in source)?
Asked 2022-Feb-01 at 15:47With regard to the Log4j JNDI remote code execution vulnerability that has been identified CVE-2021-44228 - (also see references) - I wondered if Log4j-v1.2 is also impacted, but the closest I got from source code review is the JMS-Appender.
The question is, while the posts on the Internet indicate that Log4j 1.2 is also vulnerable, I am not able to find the relevant source code for it.
Am I missing something that others have identified?
Log4j 1.2 appears to have a vulnerability in the socket-server class, but my understanding is that it needs to be enabled in the first place for it to be applicable and hence is not a passive threat unlike the JNDI-lookup vulnerability which the one identified appears to be.
Is my understanding - that Log4j v1.2 - is not vulnerable to the jndi-remote-code execution bug correct?
ReferencesThis blog post from Cloudflare also indicates the same point as from AKX....that it was introduced from Log4j 2!
Update #1 - A fork of the (now-retired) apache-log4j-1.2.x with patch fixes for few vulnerabilities identified in the older library is now available (from the original log4j author). The site is https://reload4j.qos.ch/. As of 21-Jan-2022 version 1.2.18.2 has been released. Vulnerabilities addressed to date include those pertaining to JMSAppender, SocketServer and Chainsaw vulnerabilities. Note that I am simply relaying this information. Have not verified the fixes from my end. Please refer the link for additional details.
ANSWER
Answered 2022-Jan-01 at 18:43The JNDI feature was added into Log4j 2.0-beta9.
Log4j 1.x thus does not have the vulnerable code.
QUESTION
Minecraft Plugin ClassNotFound Error from External JAR
Asked 2021-Dec-31 at 16:46I am trying to build a plugin for a Minecraft Spigot server that ultimately I would like to be able to communicate over serial with things connected to my PC (server is running locally on the PC as well).
I have been able to build and run the plugin and manipulate player/blocks in the game so I know the build process for my base plugin is working. My trouble started when I began trying to include an extra dependency: jSerialComm
I added the dependency entry in my pom.xml file:
1<dependency>
2 <groupId>com.fazecast</groupId>
3 <artifactId>jSerialComm</artifactId>
4 <version>[2.0.0,3.0.0)</version>
5 <scope>provided</scope>
6</dependency>
7
I added some basic code to import classes from jSerialComm
and do something basic with them inside of a command in my plugin:
1<dependency>
2 <groupId>com.fazecast</groupId>
3 <artifactId>jSerialComm</artifactId>
4 <version>[2.0.0,3.0.0)</version>
5 <scope>provided</scope>
6</dependency>
7import com.fazecast.jSerialComm.SerialPort;
8
9public class CommandCheck implements CommandExecutor {
10
11 @Override
12 public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
13 if (sender instanceof Player){
14 System.out.println(SerialPort.getCommPorts());
15 }
16 return false;
17 }
18}
19
This builds fine, I'm using InteliJ and it does recognize the SerialPort class (no red underlines).
But when this command runs in the game I get a Class Not Found error:
1<dependency>
2 <groupId>com.fazecast</groupId>
3 <artifactId>jSerialComm</artifactId>
4 <version>[2.0.0,3.0.0)</version>
5 <scope>provided</scope>
6</dependency>
7import com.fazecast.jSerialComm.SerialPort;
8
9public class CommandCheck implements CommandExecutor {
10
11 @Override
12 public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
13 if (sender instanceof Player){
14 System.out.println(SerialPort.getCommPorts());
15 }
16 return false;
17 }
18}
19org.bukkit.command.CommandException: Unhandled exception executing command 'check' in plugin MyFirstPlugin v1.0-SNAPSHOT
20 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
21 at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
22 at org.bukkit.craftbukkit.v1_18_R1.CraftServer.dispatchCommand(CraftServer.java:821) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
23 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1939) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
24 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1778) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
25 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1759) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
26 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:46) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
27 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
28 at net.minecraft.network.protocol.PlayerConnectionUtils.lambda$0(PlayerConnectionUtils.java:30) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
29 at net.minecraft.server.TickTask.run(SourceFile:18) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
30 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:151) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
31 at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.c(SourceFile:23) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
32 at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1158) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
33 at net.minecraft.server.MinecraftServer.c(MinecraftServer.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
34 at net.minecraft.util.thread.IAsyncTaskHandler.y(SourceFile:125) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
35 at net.minecraft.server.MinecraftServer.bf(MinecraftServer.java:1137) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
36 at net.minecraft.server.MinecraftServer.y(MinecraftServer.java:1130) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
37 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:134) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
38 at net.minecraft.server.MinecraftServer.x(MinecraftServer.java:1114) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
39 at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1038) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
40 at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:304) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
41 at java.lang.Thread.run(Thread.java:833) [?:?]
42Caused by: java.lang.NoClassDefFoundError: com/fazecast/jSerialComm/SerialPort
43 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
44 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
45 ... 21 more
46Caused by: java.lang.ClassNotFoundException: com.fazecast.jSerialComm.SerialPort
47 at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:147) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
48 at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:99) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
49 at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
50 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
51 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
52 ... 21 more
53
I have unzipped and looked inside of the built jar file and the jSerialComm jar file is successfully being included within my plugin jar:
What do I need to do in order to successfully use an external JAR file (jSerialComm specifically) from inside of a Minecraft plugin? Or alternatively, is there some built-in way that I can connect and communicate over serial ports without needing an external JAR and therefore not needing anything "special" in order to work?
ANSWER
Answered 2021-Dec-31 at 16:46Even if the JAR is present in your plugin, the classes of the JAR are not loaded in the classpath and Spigot cannot access the classes.
You can use a plugin, such as the maven-shade-plugin, which copies all classes from your API-JAR to your Plugin-JAR.
First, set the scope from provided
to compile
.
1<dependency>
2 <groupId>com.fazecast</groupId>
3 <artifactId>jSerialComm</artifactId>
4 <version>[2.0.0,3.0.0)</version>
5 <scope>provided</scope>
6</dependency>
7import com.fazecast.jSerialComm.SerialPort;
8
9public class CommandCheck implements CommandExecutor {
10
11 @Override
12 public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
13 if (sender instanceof Player){
14 System.out.println(SerialPort.getCommPorts());
15 }
16 return false;
17 }
18}
19org.bukkit.command.CommandException: Unhandled exception executing command 'check' in plugin MyFirstPlugin v1.0-SNAPSHOT
20 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
21 at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
22 at org.bukkit.craftbukkit.v1_18_R1.CraftServer.dispatchCommand(CraftServer.java:821) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
23 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1939) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
24 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1778) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
25 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1759) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
26 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:46) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
27 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
28 at net.minecraft.network.protocol.PlayerConnectionUtils.lambda$0(PlayerConnectionUtils.java:30) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
29 at net.minecraft.server.TickTask.run(SourceFile:18) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
30 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:151) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
31 at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.c(SourceFile:23) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
32 at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1158) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
33 at net.minecraft.server.MinecraftServer.c(MinecraftServer.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
34 at net.minecraft.util.thread.IAsyncTaskHandler.y(SourceFile:125) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
35 at net.minecraft.server.MinecraftServer.bf(MinecraftServer.java:1137) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
36 at net.minecraft.server.MinecraftServer.y(MinecraftServer.java:1130) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
37 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:134) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
38 at net.minecraft.server.MinecraftServer.x(MinecraftServer.java:1114) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
39 at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1038) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
40 at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:304) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
41 at java.lang.Thread.run(Thread.java:833) [?:?]
42Caused by: java.lang.NoClassDefFoundError: com/fazecast/jSerialComm/SerialPort
43 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
44 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
45 ... 21 more
46Caused by: java.lang.ClassNotFoundException: com.fazecast.jSerialComm.SerialPort
47 at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:147) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
48 at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:99) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
49 at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
50 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
51 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
52 ... 21 more
53<dependency>
54 <groupId>com.fazecast</groupId>
55 <artifactId>jSerialComm</artifactId>
56 <version>[2.0.0,3.0.0)</version>
57 <scope>compile</scope> <!-- -->
58</dependency>
59
Then add the maven-shade-plugin
under build > plugins
inside your pom.xml
1<dependency>
2 <groupId>com.fazecast</groupId>
3 <artifactId>jSerialComm</artifactId>
4 <version>[2.0.0,3.0.0)</version>
5 <scope>provided</scope>
6</dependency>
7import com.fazecast.jSerialComm.SerialPort;
8
9public class CommandCheck implements CommandExecutor {
10
11 @Override
12 public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
13 if (sender instanceof Player){
14 System.out.println(SerialPort.getCommPorts());
15 }
16 return false;
17 }
18}
19org.bukkit.command.CommandException: Unhandled exception executing command 'check' in plugin MyFirstPlugin v1.0-SNAPSHOT
20 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
21 at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
22 at org.bukkit.craftbukkit.v1_18_R1.CraftServer.dispatchCommand(CraftServer.java:821) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
23 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1939) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
24 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1778) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
25 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1759) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
26 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:46) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
27 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
28 at net.minecraft.network.protocol.PlayerConnectionUtils.lambda$0(PlayerConnectionUtils.java:30) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
29 at net.minecraft.server.TickTask.run(SourceFile:18) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
30 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:151) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
31 at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.c(SourceFile:23) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
32 at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1158) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
33 at net.minecraft.server.MinecraftServer.c(MinecraftServer.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
34 at net.minecraft.util.thread.IAsyncTaskHandler.y(SourceFile:125) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
35 at net.minecraft.server.MinecraftServer.bf(MinecraftServer.java:1137) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
36 at net.minecraft.server.MinecraftServer.y(MinecraftServer.java:1130) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
37 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:134) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
38 at net.minecraft.server.MinecraftServer.x(MinecraftServer.java:1114) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
39 at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1038) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
40 at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:304) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
41 at java.lang.Thread.run(Thread.java:833) [?:?]
42Caused by: java.lang.NoClassDefFoundError: com/fazecast/jSerialComm/SerialPort
43 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
44 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
45 ... 21 more
46Caused by: java.lang.ClassNotFoundException: com.fazecast.jSerialComm.SerialPort
47 at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:147) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
48 at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:99) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
49 at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
50 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
51 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
52 ... 21 more
53<dependency>
54 <groupId>com.fazecast</groupId>
55 <artifactId>jSerialComm</artifactId>
56 <version>[2.0.0,3.0.0)</version>
57 <scope>compile</scope> <!-- -->
58</dependency>
59<build>
60 <!-- ... -->
61 <plugins>
62 <!-- ... -->
63 <plugin>
64 <groupId>org.apache.maven.plugins</groupId>
65 <artifactId>maven-shade-plugin</artifactId>
66 <version>3.1.0</version>
67 <executions>
68 <execution>
69 <phase>package</phase>
70 <goals>
71 <goal>shade</goal>
72 </goals>
73 </execution>
74 </executions>
75 </plugin>
76 <!-- ... -->
77 </plugins>
78 <!-- ... -->
79 </build>
80
If you now build the jar (using e. g. man clean package
), there should be a "fat-" jar file in the target/ folder that contains the classes of the API as well as your classes.
Contents of your plugin before:
1<dependency>
2 <groupId>com.fazecast</groupId>
3 <artifactId>jSerialComm</artifactId>
4 <version>[2.0.0,3.0.0)</version>
5 <scope>provided</scope>
6</dependency>
7import com.fazecast.jSerialComm.SerialPort;
8
9public class CommandCheck implements CommandExecutor {
10
11 @Override
12 public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
13 if (sender instanceof Player){
14 System.out.println(SerialPort.getCommPorts());
15 }
16 return false;
17 }
18}
19org.bukkit.command.CommandException: Unhandled exception executing command 'check' in plugin MyFirstPlugin v1.0-SNAPSHOT
20 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
21 at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
22 at org.bukkit.craftbukkit.v1_18_R1.CraftServer.dispatchCommand(CraftServer.java:821) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
23 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1939) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
24 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1778) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
25 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1759) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
26 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:46) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
27 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
28 at net.minecraft.network.protocol.PlayerConnectionUtils.lambda$0(PlayerConnectionUtils.java:30) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
29 at net.minecraft.server.TickTask.run(SourceFile:18) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
30 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:151) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
31 at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.c(SourceFile:23) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
32 at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1158) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
33 at net.minecraft.server.MinecraftServer.c(MinecraftServer.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
34 at net.minecraft.util.thread.IAsyncTaskHandler.y(SourceFile:125) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
35 at net.minecraft.server.MinecraftServer.bf(MinecraftServer.java:1137) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
36 at net.minecraft.server.MinecraftServer.y(MinecraftServer.java:1130) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
37 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:134) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
38 at net.minecraft.server.MinecraftServer.x(MinecraftServer.java:1114) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
39 at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1038) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
40 at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:304) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
41 at java.lang.Thread.run(Thread.java:833) [?:?]
42Caused by: java.lang.NoClassDefFoundError: com/fazecast/jSerialComm/SerialPort
43 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
44 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
45 ... 21 more
46Caused by: java.lang.ClassNotFoundException: com.fazecast.jSerialComm.SerialPort
47 at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:147) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
48 at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:99) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
49 at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
50 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
51 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
52 ... 21 more
53<dependency>
54 <groupId>com.fazecast</groupId>
55 <artifactId>jSerialComm</artifactId>
56 <version>[2.0.0,3.0.0)</version>
57 <scope>compile</scope> <!-- -->
58</dependency>
59<build>
60 <!-- ... -->
61 <plugins>
62 <!-- ... -->
63 <plugin>
64 <groupId>org.apache.maven.plugins</groupId>
65 <artifactId>maven-shade-plugin</artifactId>
66 <version>3.1.0</version>
67 <executions>
68 <execution>
69 <phase>package</phase>
70 <goals>
71 <goal>shade</goal>
72 </goals>
73 </execution>
74 </executions>
75 </plugin>
76 <!-- ... -->
77 </plugins>
78 <!-- ... -->
79 </build>
80├ com
81 ├ foamguy
82 └ myfirstplugin
83 └ ...
84├ plugin.yml
85└ jSerialComm-xxx.jar
86
Contents of your plugin after:
1<dependency>
2 <groupId>com.fazecast</groupId>
3 <artifactId>jSerialComm</artifactId>
4 <version>[2.0.0,3.0.0)</version>
5 <scope>provided</scope>
6</dependency>
7import com.fazecast.jSerialComm.SerialPort;
8
9public class CommandCheck implements CommandExecutor {
10
11 @Override
12 public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
13 if (sender instanceof Player){
14 System.out.println(SerialPort.getCommPorts());
15 }
16 return false;
17 }
18}
19org.bukkit.command.CommandException: Unhandled exception executing command 'check' in plugin MyFirstPlugin v1.0-SNAPSHOT
20 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
21 at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
22 at org.bukkit.craftbukkit.v1_18_R1.CraftServer.dispatchCommand(CraftServer.java:821) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
23 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1939) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
24 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1778) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
25 at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1759) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
26 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:46) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
27 at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
28 at net.minecraft.network.protocol.PlayerConnectionUtils.lambda$0(PlayerConnectionUtils.java:30) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
29 at net.minecraft.server.TickTask.run(SourceFile:18) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
30 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:151) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
31 at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.c(SourceFile:23) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
32 at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1158) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
33 at net.minecraft.server.MinecraftServer.c(MinecraftServer.java:1) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
34 at net.minecraft.util.thread.IAsyncTaskHandler.y(SourceFile:125) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
35 at net.minecraft.server.MinecraftServer.bf(MinecraftServer.java:1137) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
36 at net.minecraft.server.MinecraftServer.y(MinecraftServer.java:1130) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
37 at net.minecraft.util.thread.IAsyncTaskHandler.c(SourceFile:134) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
38 at net.minecraft.server.MinecraftServer.x(MinecraftServer.java:1114) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
39 at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1038) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
40 at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:304) ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3380-Spigot-8965a50-0ba6b90]
41 at java.lang.Thread.run(Thread.java:833) [?:?]
42Caused by: java.lang.NoClassDefFoundError: com/fazecast/jSerialComm/SerialPort
43 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
44 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
45 ... 21 more
46Caused by: java.lang.ClassNotFoundException: com.fazecast.jSerialComm.SerialPort
47 at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:147) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
48 at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:99) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
49 at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
50 at com.foamyguy.myfirstplugin.CommandCheck.onCommand(CommandCheck.java:21) ~[?:?]
51 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?]
52 ... 21 more
53<dependency>
54 <groupId>com.fazecast</groupId>
55 <artifactId>jSerialComm</artifactId>
56 <version>[2.0.0,3.0.0)</version>
57 <scope>compile</scope> <!-- -->
58</dependency>
59<build>
60 <!-- ... -->
61 <plugins>
62 <!-- ... -->
63 <plugin>
64 <groupId>org.apache.maven.plugins</groupId>
65 <artifactId>maven-shade-plugin</artifactId>
66 <version>3.1.0</version>
67 <executions>
68 <execution>
69 <phase>package</phase>
70 <goals>
71 <goal>shade</goal>
72 </goals>
73 </execution>
74 </executions>
75 </plugin>
76 <!-- ... -->
77 </plugins>
78 <!-- ... -->
79 </build>
80├ com
81 ├ foamguy
82 └ myfirstplugin
83 └ ...
84├ plugin.yml
85└ jSerialComm-xxx.jar
86├ com
87 ├ foamguy
88 └ myfirstplugin
89 └ ...
90 └ fazecast
91 └ jSerialComm
92 └ ...
93└ plugin.yml
94
QUESTION
Infer dependencies in Gradle subproject from its parent project
Asked 2021-Dec-15 at 04:07I currently have 3 subprojects in my Gradle project, structured like so:
1Main Project
2|
3-- Project A
4-- Project B
5-- Common Src
6
Project A has dependency on Lib A and Common Src, and Project B has dependency on Lib B and Common Src. Lib A and Lib B contain different implementations of the same classes.
My plan for Common Src project was to house all of the utility classes, necessarily depending on both Lib A and Lib B.
Is there a way to set this up, and how should my gradle project look like?
Things that I've tried:- I've tried to remove Common Src as a subproject and just include it in the sourceSets of Project A and Project B. However, IntelliJ seems to mark Common Src as sources root of Project A, and even though build-through-gradle works, I cannot get IntelliJ to recognize that Project B also has sources root in Common Src.
- Add both Lib A and Lib B to dependency of Common Src, but obviously that doesn't work.
I've created a Minecraft mod compatible with both Forge (Project A) and Fabric (Project B) modloaders. I have utility classes in both projects that have the same source code but need to be compiled twice, each time with a different dependency. I don't want to have to write the code twice each time I want to change something in the Utility classes.
ANSWER
Answered 2021-Dec-15 at 04:07EDIT: I've found a workaround:
- In both
Project A
andProject B
, add a task in each of theirbuild.gradle
to copy the source files fromCommon Src
to the build directory of each project. - Configure
sourceSets
of bothProject A
andProject B
to include source files from the build folder we just copied into - Configure
Common Src
to be a gradle subproject, and addLib A
(orLib B
) to the dependencies ofCommon Src
(just to get IntelliJ some context)
QUESTION
Minecraft Forge 1.7.10 Custom Entity Not Spawning On The Client?
Asked 2021-Dec-02 at 22:58In my Minecraft Forge mod for 1.7.10. I am aware that this version is arguably old news, but it is my favorite version and all of my modding experience is with this version.
I am creating a custom TNT block. The issue is the primed version is not rendering. When ignited, the TNT disappears, and then shortly later there is an explosion. If the TNT was placed in the air, the explosion is below like it should be due to the primed TNT falling. The issue is that it is not rendering. When I use fn+f3+b to show hitboxes, no hitbox is shown.
The issue is the entity being spawned on the server does not replicate to the client. I know this because:
Switching out the entity renderer with the default
RenderTNTPrimed
still fails to render at all instead of rendering the default TNT hence my custom renderer class cannot be the issue.Switching out my custom entity class with the copy paste vanilla
EntityTNTPrimed
code also does not solve the problem. If the problem was with my custom entity class then using bona fide vanilla code would fix the problem but it doesnt.The entity and its renderer are being registered using
RenderingRegistry.registerEntityRenderingHandler()
from the client proxy andEntityRegistry.registerGlobalEntityID()
thenEntityRegistry.registerModEntity()
ininit()
(I had tested the client proxy withSystem.out.println()
and the client proxy works).Though the largest evidence of the problem being the TNT spawing on the server but not the client is the fact that removing
if(world.isRemote) return;
from the handlers in myBlockTNT
class causes the TNT to render. However I am not supposed to handle igniting the TNT on the client so I am not supposed to have to removeif(world.isRemote) return;
. Besides doing this is a pseudo fix, because the entity is still invisible when/summon
ed.The constructor for
TNTPrimedCharged
is only being called from the server, andonUpdate()
forTNTPrimed
and thusTNTPrimedCharged
is also only being called by the server, as demostrated by adding print statements and the logs only show them printed from the SERVER thread.
The BlockTNT
class (much of this is derived from vanilla code, but has been designed to take the corresponding custom primed TNT entity class while instantiating, the problem is not here because instantiating a default EntityTNTPrimed
instead of the provided primed
class does render correctly, but I have included this because this code helped demonstrate the origin of the problem):
1class BlockTNT extends net.minecraft.block.BlockTNT {
2 private final Class primed;
3 public BlockTNT(final Class primed) {
4 this.primed = primed;
5 stepSound = net.minecraft.block.Block.soundTypeGrass;
6 }
7 protected EntityTNTPrimed getPrimed(final World world, final int x, final int y, final int z, final EntityLivingBase igniter) {
8 try {
9 return (EntityTNTPrimed)primed.getDeclaredConstructor(World.class, double.class, double.class, double.class, EntityLivingBase.class).newInstance(world, (double)((float)x+0.5F), (double)((float)y+0.5F), (double)((float)z+0.5F), igniter);
10 } catch (Exception exception) {
11 return null;
12 }
13 }
14 @Override public void onBlockDestroyedByExplosion(final World world, final int x, final int y, final int z, final Explosion explosion) {
15 if(world.isRemote)
16 return;
17 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, explosion.getExplosivePlacedBy());
18 tnt.fuse = world.rand.nextInt(tnt.fuse>>2)+(tnt.fuse>>3);
19 world.spawnEntityInWorld(tnt);
20 }
21 @Override public void func_150114_a(final World world, final int x, final int y, final int z, final int meta, final EntityLivingBase igniter) {
22 if(world.isRemote || (meta&1) == 0)
23 return;
24 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, igniter);
25 world.spawnEntityInWorld(tnt);
26 world.playSoundAtEntity(tnt, "game.tnt.primed", 1.0F, 1.0F);
27 }
28}
29
Inside the main mod class I register the entities:
1class BlockTNT extends net.minecraft.block.BlockTNT {
2 private final Class primed;
3 public BlockTNT(final Class primed) {
4 this.primed = primed;
5 stepSound = net.minecraft.block.Block.soundTypeGrass;
6 }
7 protected EntityTNTPrimed getPrimed(final World world, final int x, final int y, final int z, final EntityLivingBase igniter) {
8 try {
9 return (EntityTNTPrimed)primed.getDeclaredConstructor(World.class, double.class, double.class, double.class, EntityLivingBase.class).newInstance(world, (double)((float)x+0.5F), (double)((float)y+0.5F), (double)((float)z+0.5F), igniter);
10 } catch (Exception exception) {
11 return null;
12 }
13 }
14 @Override public void onBlockDestroyedByExplosion(final World world, final int x, final int y, final int z, final Explosion explosion) {
15 if(world.isRemote)
16 return;
17 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, explosion.getExplosivePlacedBy());
18 tnt.fuse = world.rand.nextInt(tnt.fuse>>2)+(tnt.fuse>>3);
19 world.spawnEntityInWorld(tnt);
20 }
21 @Override public void func_150114_a(final World world, final int x, final int y, final int z, final int meta, final EntityLivingBase igniter) {
22 if(world.isRemote || (meta&1) == 0)
23 return;
24 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, igniter);
25 world.spawnEntityInWorld(tnt);
26 world.playSoundAtEntity(tnt, "game.tnt.primed", 1.0F, 1.0F);
27 }
28}
29@Instance public static ExampleMod instance;
30@SidedProxy(clientSide="com.examplemod.ClientProxy", serverSide="com.examplemod.CommonProxy") public static com.examplemod.CommonProxy proxy;
31private static void registerTnt(final Class primed, String name, final int id) {
32 proxy.registerTntRenderer(primed, registerBlock(new BlockTNT(primed), name.toLowerCase()+"_tnt"));
33 EntityRegistry.registerGlobalEntityID(primed, name = "PrimedTnt"+name, EntityRegistry.findGlobalUniqueEntityId());
34 EntityRegistry.registerModEntity(primed, name, id, instance, 160, 10, true);
35}
36@EventHandler public void init(FMLInitializationEvent event) {
37 registerTnt(com.examplemod.TNTPrimedCharged.class, "Charged", 0);
38 // ...
39}
40
And we register the renderer in the client proxy (again tested and works):
1class BlockTNT extends net.minecraft.block.BlockTNT {
2 private final Class primed;
3 public BlockTNT(final Class primed) {
4 this.primed = primed;
5 stepSound = net.minecraft.block.Block.soundTypeGrass;
6 }
7 protected EntityTNTPrimed getPrimed(final World world, final int x, final int y, final int z, final EntityLivingBase igniter) {
8 try {
9 return (EntityTNTPrimed)primed.getDeclaredConstructor(World.class, double.class, double.class, double.class, EntityLivingBase.class).newInstance(world, (double)((float)x+0.5F), (double)((float)y+0.5F), (double)((float)z+0.5F), igniter);
10 } catch (Exception exception) {
11 return null;
12 }
13 }
14 @Override public void onBlockDestroyedByExplosion(final World world, final int x, final int y, final int z, final Explosion explosion) {
15 if(world.isRemote)
16 return;
17 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, explosion.getExplosivePlacedBy());
18 tnt.fuse = world.rand.nextInt(tnt.fuse>>2)+(tnt.fuse>>3);
19 world.spawnEntityInWorld(tnt);
20 }
21 @Override public void func_150114_a(final World world, final int x, final int y, final int z, final int meta, final EntityLivingBase igniter) {
22 if(world.isRemote || (meta&1) == 0)
23 return;
24 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, igniter);
25 world.spawnEntityInWorld(tnt);
26 world.playSoundAtEntity(tnt, "game.tnt.primed", 1.0F, 1.0F);
27 }
28}
29@Instance public static ExampleMod instance;
30@SidedProxy(clientSide="com.examplemod.ClientProxy", serverSide="com.examplemod.CommonProxy") public static com.examplemod.CommonProxy proxy;
31private static void registerTnt(final Class primed, String name, final int id) {
32 proxy.registerTntRenderer(primed, registerBlock(new BlockTNT(primed), name.toLowerCase()+"_tnt"));
33 EntityRegistry.registerGlobalEntityID(primed, name = "PrimedTnt"+name, EntityRegistry.findGlobalUniqueEntityId());
34 EntityRegistry.registerModEntity(primed, name, id, instance, 160, 10, true);
35}
36@EventHandler public void init(FMLInitializationEvent event) {
37 registerTnt(com.examplemod.TNTPrimedCharged.class, "Charged", 0);
38 // ...
39}
40@Override public void registerTntRenderer(final Class primed, final Block block) {
41 RenderingRegistry.registerEntityRenderingHandler(primed, new com.examplemod.RenderTNTPrimed(block));
42}
43
Here is the class for the custom entities:
1class BlockTNT extends net.minecraft.block.BlockTNT {
2 private final Class primed;
3 public BlockTNT(final Class primed) {
4 this.primed = primed;
5 stepSound = net.minecraft.block.Block.soundTypeGrass;
6 }
7 protected EntityTNTPrimed getPrimed(final World world, final int x, final int y, final int z, final EntityLivingBase igniter) {
8 try {
9 return (EntityTNTPrimed)primed.getDeclaredConstructor(World.class, double.class, double.class, double.class, EntityLivingBase.class).newInstance(world, (double)((float)x+0.5F), (double)((float)y+0.5F), (double)((float)z+0.5F), igniter);
10 } catch (Exception exception) {
11 return null;
12 }
13 }
14 @Override public void onBlockDestroyedByExplosion(final World world, final int x, final int y, final int z, final Explosion explosion) {
15 if(world.isRemote)
16 return;
17 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, explosion.getExplosivePlacedBy());
18 tnt.fuse = world.rand.nextInt(tnt.fuse>>2)+(tnt.fuse>>3);
19 world.spawnEntityInWorld(tnt);
20 }
21 @Override public void func_150114_a(final World world, final int x, final int y, final int z, final int meta, final EntityLivingBase igniter) {
22 if(world.isRemote || (meta&1) == 0)
23 return;
24 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, igniter);
25 world.spawnEntityInWorld(tnt);
26 world.playSoundAtEntity(tnt, "game.tnt.primed", 1.0F, 1.0F);
27 }
28}
29@Instance public static ExampleMod instance;
30@SidedProxy(clientSide="com.examplemod.ClientProxy", serverSide="com.examplemod.CommonProxy") public static com.examplemod.CommonProxy proxy;
31private static void registerTnt(final Class primed, String name, final int id) {
32 proxy.registerTntRenderer(primed, registerBlock(new BlockTNT(primed), name.toLowerCase()+"_tnt"));
33 EntityRegistry.registerGlobalEntityID(primed, name = "PrimedTnt"+name, EntityRegistry.findGlobalUniqueEntityId());
34 EntityRegistry.registerModEntity(primed, name, id, instance, 160, 10, true);
35}
36@EventHandler public void init(FMLInitializationEvent event) {
37 registerTnt(com.examplemod.TNTPrimedCharged.class, "Charged", 0);
38 // ...
39}
40@Override public void registerTntRenderer(final Class primed, final Block block) {
41 RenderingRegistry.registerEntityRenderingHandler(primed, new com.examplemod.RenderTNTPrimed(block));
42}
43public abstract class TNTPrimed extends net.minecraft.entity.item.EntityTNTPrimed {
44 public TNTPrimed(final World world, final double x, final double y, final double z, final EntityLivingBase igniter) {
45 super(world, x, y, z, igniter);
46 }
47 public TNTPrimed(final World world) {
48 super(world);
49 }
50 @Override public void onUpdate() {
51 prevPosX = posX;
52 prevPosY = posY;
53 prevPosZ = posZ;
54 moveEntity(motionX, motionY -= 0.04D, motionZ);
55 motionX *= 0.98D;
56 motionY *= 0.98D;
57 motionZ *= 0.98D;
58 if(onGround) {
59 motionX *= 0.7D;
60 motionZ *= 0.7D;
61 motionY *= -0.5D;
62 }
63 if(fuse-- <= 0) {
64 setDead();
65 if(!worldObj.isRemote)
66 explode();
67 } else
68 worldObj.spawnParticle("smoke", posX, posY+0.5D, posZ, 0.0D, 0.0D, 0.0D);
69 }
70 protected abstract void explode();
71}
72
1class BlockTNT extends net.minecraft.block.BlockTNT {
2 private final Class primed;
3 public BlockTNT(final Class primed) {
4 this.primed = primed;
5 stepSound = net.minecraft.block.Block.soundTypeGrass;
6 }
7 protected EntityTNTPrimed getPrimed(final World world, final int x, final int y, final int z, final EntityLivingBase igniter) {
8 try {
9 return (EntityTNTPrimed)primed.getDeclaredConstructor(World.class, double.class, double.class, double.class, EntityLivingBase.class).newInstance(world, (double)((float)x+0.5F), (double)((float)y+0.5F), (double)((float)z+0.5F), igniter);
10 } catch (Exception exception) {
11 return null;
12 }
13 }
14 @Override public void onBlockDestroyedByExplosion(final World world, final int x, final int y, final int z, final Explosion explosion) {
15 if(world.isRemote)
16 return;
17 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, explosion.getExplosivePlacedBy());
18 tnt.fuse = world.rand.nextInt(tnt.fuse>>2)+(tnt.fuse>>3);
19 world.spawnEntityInWorld(tnt);
20 }
21 @Override public void func_150114_a(final World world, final int x, final int y, final int z, final int meta, final EntityLivingBase igniter) {
22 if(world.isRemote || (meta&1) == 0)
23 return;
24 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, igniter);
25 world.spawnEntityInWorld(tnt);
26 world.playSoundAtEntity(tnt, "game.tnt.primed", 1.0F, 1.0F);
27 }
28}
29@Instance public static ExampleMod instance;
30@SidedProxy(clientSide="com.examplemod.ClientProxy", serverSide="com.examplemod.CommonProxy") public static com.examplemod.CommonProxy proxy;
31private static void registerTnt(final Class primed, String name, final int id) {
32 proxy.registerTntRenderer(primed, registerBlock(new BlockTNT(primed), name.toLowerCase()+"_tnt"));
33 EntityRegistry.registerGlobalEntityID(primed, name = "PrimedTnt"+name, EntityRegistry.findGlobalUniqueEntityId());
34 EntityRegistry.registerModEntity(primed, name, id, instance, 160, 10, true);
35}
36@EventHandler public void init(FMLInitializationEvent event) {
37 registerTnt(com.examplemod.TNTPrimedCharged.class, "Charged", 0);
38 // ...
39}
40@Override public void registerTntRenderer(final Class primed, final Block block) {
41 RenderingRegistry.registerEntityRenderingHandler(primed, new com.examplemod.RenderTNTPrimed(block));
42}
43public abstract class TNTPrimed extends net.minecraft.entity.item.EntityTNTPrimed {
44 public TNTPrimed(final World world, final double x, final double y, final double z, final EntityLivingBase igniter) {
45 super(world, x, y, z, igniter);
46 }
47 public TNTPrimed(final World world) {
48 super(world);
49 }
50 @Override public void onUpdate() {
51 prevPosX = posX;
52 prevPosY = posY;
53 prevPosZ = posZ;
54 moveEntity(motionX, motionY -= 0.04D, motionZ);
55 motionX *= 0.98D;
56 motionY *= 0.98D;
57 motionZ *= 0.98D;
58 if(onGround) {
59 motionX *= 0.7D;
60 motionZ *= 0.7D;
61 motionY *= -0.5D;
62 }
63 if(fuse-- <= 0) {
64 setDead();
65 if(!worldObj.isRemote)
66 explode();
67 } else
68 worldObj.spawnParticle("smoke", posX, posY+0.5D, posZ, 0.0D, 0.0D, 0.0D);
69 }
70 protected abstract void explode();
71}
72public class TNTPrimedCharged extends com.examplemod.TNTPrimed {
73 public TNTPrimedCharged(final World world, final double x, final double y, final double z, final EntityLivingBase igniter) {
74 super(world, x, y, z, igniter);
75 }
76 public TNTPrimedCharged(final World world) {
77 super(world);
78 }
79 @Override protected void explode() {
80 worldObj.newExplosion(this, posX, posY, posZ, 8, false, true);
81 }
82}
83
Though I can state categorically that the custom entity renderer class is not the culprit, I am providing it for reference:
1class BlockTNT extends net.minecraft.block.BlockTNT {
2 private final Class primed;
3 public BlockTNT(final Class primed) {
4 this.primed = primed;
5 stepSound = net.minecraft.block.Block.soundTypeGrass;
6 }
7 protected EntityTNTPrimed getPrimed(final World world, final int x, final int y, final int z, final EntityLivingBase igniter) {
8 try {
9 return (EntityTNTPrimed)primed.getDeclaredConstructor(World.class, double.class, double.class, double.class, EntityLivingBase.class).newInstance(world, (double)((float)x+0.5F), (double)((float)y+0.5F), (double)((float)z+0.5F), igniter);
10 } catch (Exception exception) {
11 return null;
12 }
13 }
14 @Override public void onBlockDestroyedByExplosion(final World world, final int x, final int y, final int z, final Explosion explosion) {
15 if(world.isRemote)
16 return;
17 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, explosion.getExplosivePlacedBy());
18 tnt.fuse = world.rand.nextInt(tnt.fuse>>2)+(tnt.fuse>>3);
19 world.spawnEntityInWorld(tnt);
20 }
21 @Override public void func_150114_a(final World world, final int x, final int y, final int z, final int meta, final EntityLivingBase igniter) {
22 if(world.isRemote || (meta&1) == 0)
23 return;
24 final EntityTNTPrimed tnt = getPrimed(world, x, y, z, igniter);
25 world.spawnEntityInWorld(tnt);
26 world.playSoundAtEntity(tnt, "game.tnt.primed", 1.0F, 1.0F);
27 }
28}
29@Instance public static ExampleMod instance;
30@SidedProxy(clientSide="com.examplemod.ClientProxy", serverSide="com.examplemod.CommonProxy") public static com.examplemod.CommonProxy proxy;
31private static void registerTnt(final Class primed, String name, final int id) {
32 proxy.registerTntRenderer(primed, registerBlock(new BlockTNT(primed), name.toLowerCase()+"_tnt"));
33 EntityRegistry.registerGlobalEntityID(primed, name = "PrimedTnt"+name, EntityRegistry.findGlobalUniqueEntityId());
34 EntityRegistry.registerModEntity(primed, name, id, instance, 160, 10, true);
35}
36@EventHandler public void init(FMLInitializationEvent event) {
37 registerTnt(com.examplemod.TNTPrimedCharged.class, "Charged", 0);
38 // ...
39}
40@Override public void registerTntRenderer(final Class primed, final Block block) {
41 RenderingRegistry.registerEntityRenderingHandler(primed, new com.examplemod.RenderTNTPrimed(block));
42}
43public abstract class TNTPrimed extends net.minecraft.entity.item.EntityTNTPrimed {
44 public TNTPrimed(final World world, final double x, final double y, final double z, final EntityLivingBase igniter) {
45 super(world, x, y, z, igniter);
46 }
47 public TNTPrimed(final World world) {
48 super(world);
49 }
50 @Override public void onUpdate() {
51 prevPosX = posX;
52 prevPosY = posY;
53 prevPosZ = posZ;
54 moveEntity(motionX, motionY -= 0.04D, motionZ);
55 motionX *= 0.98D;
56 motionY *= 0.98D;
57 motionZ *= 0.98D;
58 if(onGround) {
59 motionX *= 0.7D;
60 motionZ *= 0.7D;
61 motionY *= -0.5D;
62 }
63 if(fuse-- <= 0) {
64 setDead();
65 if(!worldObj.isRemote)
66 explode();
67 } else
68 worldObj.spawnParticle("smoke", posX, posY+0.5D, posZ, 0.0D, 0.0D, 0.0D);
69 }
70 protected abstract void explode();
71}
72public class TNTPrimedCharged extends com.examplemod.TNTPrimed {
73 public TNTPrimedCharged(final World world, final double x, final double y, final double z, final EntityLivingBase igniter) {
74 super(world, x, y, z, igniter);
75 }
76 public TNTPrimedCharged(final World world) {
77 super(world);
78 }
79 @Override protected void explode() {
80 worldObj.newExplosion(this, posX, posY, posZ, 8, false, true);
81 }
82}
83class RenderTNTPrimed extends net.minecraft.client.renderer.entity.RenderTNTPrimed {
84 private final RenderBlocks renderer = new RenderBlocks();
85 private final Block block;
86 public RenderTNTPrimed(final Block block) {
87 super();
88 this.block = block;
89 }
90 @Override public void doRender(final EntityTNTPrimed entity, final double x, final double y, final double z, final float yaw, final float tick) {
91 GL11.glPushMatrix();
92 GL11.glTranslatef((float)x, (float)y, (float)z);
93 float var0 = entity.fuse-tick+1.0F;
94 if (var0 < 10.0F) {
95 final float scale = (float)Math.pow(Math.max(Math.min(1-var0/10, 1.0F), 0.0F), 4.0F)*0.3F+1.0F;
96 GL11.glScalef(scale, scale, scale);
97 }
98 bindEntityTexture(entity);
99 renderer.renderBlockAsItem(block, 0, entity.getBrightness(tick));
100 if (((entity.fuse/5)&1) == 0) {
101 GL11.glDisable(GL11.GL_TEXTURE_2D);
102 GL11.glDisable(GL11.GL_LIGHTING);
103 GL11.glEnable(GL11.GL_BLEND);
104 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_DST_ALPHA);
105 GL11.glColor4f(1.0F, 1.0F, 1.0F, (1.0F-var0/100.0F)*0.8F);
106 renderer.renderBlockAsItem(block, 0, 1.0F);
107 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
108 GL11.glDisable(GL11.GL_BLEND);
109 GL11.glEnable(GL11.GL_LIGHTING);
110 GL11.glEnable(GL11.GL_TEXTURE_2D);
111 }
112 GL11.glPopMatrix();
113 }
114}
115
So when the server calls world.spawnEntityInWorld()
on my custom entity why does it fail to spawn it on the client as well? How can I fix this because the TNT just disappearing when being ignited is undesirable and I have no idea what else to try. How can I make the custom primed TNT show up on the client?
Upon reverse engineering other similar mods (specifically the Too Much TNT mod), their TNT primed entities successfully render when /summon
is used, and they do check for clientside in their TNT block classes. After investigation, I cannot tell what they are doing differently that would cause their entities to render but not mine.
I have spent several unfruitful hours researching this problem, and given that as of this edit this question is second hit for Googling basic search terms like 'Minecraft Forge 1.7.10 Entity Not Rendering' and third for 'Minecraft Forge 1.7.10 Entity Invisible,' it is very likely that further research will be in vain.
The problem is simply that when my mod added entity is spawned on the server thread, it is not also spawned on the client thread, even though it should be. How do I fix this? I tried everything.
ANSWER
Answered 2021-Dec-02 at 22:58It turns out the problem was actually not the entity not spawning on the client. The issue was that the fuse
property was being set to 0 on the client even though it is set to 80 on the server. And thus the client side TNT is instantly setDead()
ing itself. Implementing cpw.mods.fml.common.registry.IEntityAdditionalSpawnData
and then setting the fuse property to the correct value in readSpawnData
seems to have solved the problem.
QUESTION
Generate custom ores in custom dimension
Asked 2021-Nov-25 at 16:54I have recently created a custom dimension using data packs in Minecraft 1.16.5. This dimension is a part of a mod that I am writing and I am currently trying to generate custom ores in that dimension; However, I was not able to generate ores in a custom dimension the same way that I generate ores in the Overworld or Nether. As I mentioned the dimension is handled via data packs (.json files) but the biomes are handled in game code (.java). I am very new to Java & modding, any suggestions would be appreciated. Thanks in advance.
Minecraft version : 1.16.5
Forge version : 36.2.9
The current code for Overworld & Nether ore gen :
1public class OreGeneration
2{
3 public static void generateOres(final BiomeLoadingEvent event)
4 {
5 // Gigalium :
6 if(!(event.getCategory().equals(Biome.Category.THEEND)))
7 {
8 // Nether :
9 if(event.getCategory().equals(Biome.Category.NETHER))
10 {
11 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NETHERRACK, BlockInit.GIGALIUM_NETHER_ORE.get().defaultBlockState(), 6, 25, 50, 2);
12 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NETHERRACK, BlockInit.GIGALIUM_NETHER_ORE.get().defaultBlockState(), 4, 51, 120, 2);
13 }
14
15 // Overworld :
16 if(event.getCategory().equals(Biome.Category.SWAMP) || event.getCategory().equals(Biome.Category.TAIGA))
17 {
18 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 5, 12, 15, 2);
19 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 4, 16, 20, 2);
20 }
21
22 if(!(event.getCategory().equals(Biome.Category.SWAMP) && event.getCategory().equals(Biome.Category.TAIGA)))
23 {
24 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 4, 10, 13, 1);
25 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 3, 14, 18, 1);
26 }
27 }
28 }
29
30 private static void generateOre(BiomeGenerationSettingsBuilder settings, RuleTest fillerType, BlockState state, int veinSize, int minHeight, int maxHeight, int amount)
31 {
32 settings.addFeature(GenerationStage.Decoration.UNDERGROUND_ORES, Feature.ORE.configured(new OreFeatureConfig(fillerType, state, veinSize)).decorated(Placement.RANGE.configured(new TopSolidRangeConfig(minHeight, 0, maxHeight))).squared().count(amount));
33 }
34}
35
Dimension code :
1public class OreGeneration
2{
3 public static void generateOres(final BiomeLoadingEvent event)
4 {
5 // Gigalium :
6 if(!(event.getCategory().equals(Biome.Category.THEEND)))
7 {
8 // Nether :
9 if(event.getCategory().equals(Biome.Category.NETHER))
10 {
11 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NETHERRACK, BlockInit.GIGALIUM_NETHER_ORE.get().defaultBlockState(), 6, 25, 50, 2);
12 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NETHERRACK, BlockInit.GIGALIUM_NETHER_ORE.get().defaultBlockState(), 4, 51, 120, 2);
13 }
14
15 // Overworld :
16 if(event.getCategory().equals(Biome.Category.SWAMP) || event.getCategory().equals(Biome.Category.TAIGA))
17 {
18 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 5, 12, 15, 2);
19 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 4, 16, 20, 2);
20 }
21
22 if(!(event.getCategory().equals(Biome.Category.SWAMP) && event.getCategory().equals(Biome.Category.TAIGA)))
23 {
24 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 4, 10, 13, 1);
25 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 3, 14, 18, 1);
26 }
27 }
28 }
29
30 private static void generateOre(BiomeGenerationSettingsBuilder settings, RuleTest fillerType, BlockState state, int veinSize, int minHeight, int maxHeight, int amount)
31 {
32 settings.addFeature(GenerationStage.Decoration.UNDERGROUND_ORES, Feature.ORE.configured(new OreFeatureConfig(fillerType, state, veinSize)).decorated(Placement.RANGE.configured(new TopSolidRangeConfig(minHeight, 0, maxHeight))).squared().count(amount));
33 }
34}
35{
36 "type": "gigawhat_gigamod:gigaland",
37 "generator": {
38 "type": "minecraft:noise",
39 "seed": 0,
40 "settings": {
41 "bedrock_roof_position": -10,
42 "bedrock_floor_position": 0,
43 "sea_level": 80,
44 "disable_mob_generation": true,
45 "default_block": {
46 "Name": "gigawhat_gigamod:gigastone"
47 },
48 "default_fluid": {
49 "Name": "minecraft:water",
50 "Properties": {
51 "level": "0"
52 }
53 },
54 "noise": {
55 "height": 256,
56 "density_factor": 1,
57 "density_offset": -0.46875,
58 "size_horizontal": 1,
59 "size_vertical": 2,
60 "simplex_surface_noise": true,
61 "random_density_offset": true,
62 "amplified": true,
63 "sampling": {
64 "xz_scale": 1,
65 "y_scale": 1,
66 "xz_factor": 80,
67 "y_factor": 160
68 },
69 "bottom_slide": {
70 "target": -30,
71 "size": 0,
72 "offset": 0
73 },
74 "top_slide": {
75 "target": -10,
76 "size": 3,
77 "offset": 0
78 }
79 },
80 "structures": {
81 "structures": {}
82 }
83 },
84 "biome_source": {
85 "type": "minecraft:fixed",
86 "biome": "gigawhat_gigamod:gigaland_main_biome"
87 }
88 }
89}
90
Biome Init code :
1public class OreGeneration
2{
3 public static void generateOres(final BiomeLoadingEvent event)
4 {
5 // Gigalium :
6 if(!(event.getCategory().equals(Biome.Category.THEEND)))
7 {
8 // Nether :
9 if(event.getCategory().equals(Biome.Category.NETHER))
10 {
11 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NETHERRACK, BlockInit.GIGALIUM_NETHER_ORE.get().defaultBlockState(), 6, 25, 50, 2);
12 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NETHERRACK, BlockInit.GIGALIUM_NETHER_ORE.get().defaultBlockState(), 4, 51, 120, 2);
13 }
14
15 // Overworld :
16 if(event.getCategory().equals(Biome.Category.SWAMP) || event.getCategory().equals(Biome.Category.TAIGA))
17 {
18 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 5, 12, 15, 2);
19 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 4, 16, 20, 2);
20 }
21
22 if(!(event.getCategory().equals(Biome.Category.SWAMP) && event.getCategory().equals(Biome.Category.TAIGA)))
23 {
24 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 4, 10, 13, 1);
25 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 3, 14, 18, 1);
26 }
27 }
28 }
29
30 private static void generateOre(BiomeGenerationSettingsBuilder settings, RuleTest fillerType, BlockState state, int veinSize, int minHeight, int maxHeight, int amount)
31 {
32 settings.addFeature(GenerationStage.Decoration.UNDERGROUND_ORES, Feature.ORE.configured(new OreFeatureConfig(fillerType, state, veinSize)).decorated(Placement.RANGE.configured(new TopSolidRangeConfig(minHeight, 0, maxHeight))).squared().count(amount));
33 }
34}
35{
36 "type": "gigawhat_gigamod:gigaland",
37 "generator": {
38 "type": "minecraft:noise",
39 "seed": 0,
40 "settings": {
41 "bedrock_roof_position": -10,
42 "bedrock_floor_position": 0,
43 "sea_level": 80,
44 "disable_mob_generation": true,
45 "default_block": {
46 "Name": "gigawhat_gigamod:gigastone"
47 },
48 "default_fluid": {
49 "Name": "minecraft:water",
50 "Properties": {
51 "level": "0"
52 }
53 },
54 "noise": {
55 "height": 256,
56 "density_factor": 1,
57 "density_offset": -0.46875,
58 "size_horizontal": 1,
59 "size_vertical": 2,
60 "simplex_surface_noise": true,
61 "random_density_offset": true,
62 "amplified": true,
63 "sampling": {
64 "xz_scale": 1,
65 "y_scale": 1,
66 "xz_factor": 80,
67 "y_factor": 160
68 },
69 "bottom_slide": {
70 "target": -30,
71 "size": 0,
72 "offset": 0
73 },
74 "top_slide": {
75 "target": -10,
76 "size": 3,
77 "offset": 0
78 }
79 },
80 "structures": {
81 "structures": {}
82 }
83 },
84 "biome_source": {
85 "type": "minecraft:fixed",
86 "biome": "gigawhat_gigamod:gigaland_main_biome"
87 }
88 }
89}
90public class ModBiomes
91{
92 public static final DeferredRegister<Biome> BIOMES = DeferredRegister.create(ForgeRegistries.BIOMES, Gigamod.MOD_ID);
93
94 public static final RegistryObject<Biome> GIGALAND_MAIN_BIOME = BIOMES.register("gigaland_main_biome", () -> makeGigalandMainBiome(() -> ModConfiguredSurfaceBuilders.GIGALAND_SURFACE, 0.205f, 0.02f));
95
96 private static Biome makeGigalandMainBiome(final Supplier<ConfiguredSurfaceBuilder<?>> surfaceBuilder, float depth, float scale)
97 {
98 MobSpawnInfo.Builder mobspawninfo$builder = new MobSpawnInfo.Builder();
99 BiomeGenerationSettings.Builder biomegenerationsettings$builder = (new BiomeGenerationSettings.Builder()).surfaceBuilder(surfaceBuilder);
100
101 DefaultBiomeFeatures.addDefaultOverworldLandStructures(biomegenerationsettings$builder);
102 biomegenerationsettings$builder.addStructureStart(StructureFeatures.MINESHAFT);
103
104 DefaultBiomeFeatures.addDefaultCarvers(biomegenerationsettings$builder);
105 DefaultBiomeFeatures.addDefaultUndergroundVariety(biomegenerationsettings$builder);
106
107 mobspawninfo$builder.addSpawn(EntityClassification.MONSTER, new MobSpawnInfo.Spawners(EntityType.BLAZE, 100, 10, 15));
108
109 return (new Biome.Builder()).precipitation(RainType.RAIN).biomeCategory(Category.EXTREME_HILLS).depth(depth).scale(scale).temperature(1.5F).downfall(0.9F).specialEffects((new BiomeAmbience.Builder()).waterColor(65518).waterFogColor(16763760).fogColor(16763760).skyColor(16763760).foliageColorOverride(9547008).grassColorOverride(9547008).ambientParticle(new ParticleEffectAmbience(ParticleTypes.LAVA, 0.003f)).skyColor(16763760).ambientLoopSound(SoundEvents.AMBIENT_CRIMSON_FOREST_LOOP).ambientMoodSound(new MoodSoundAmbience(SoundEvents.AMBIENT_WARPED_FOREST_MOOD, 6000, 8, 2.0D)).ambientAdditionsSound(new SoundAdditionsAmbience(SoundEvents.AMBIENT_NETHER_WASTES_MOOD, 0.0111D)).build()).mobSpawnSettings(mobspawninfo$builder.build()).generationSettings(biomegenerationsettings$builder.build()).build();
110 }
111
112 public static void register(IEventBus eventBus)
113 {
114 BIOMES.register(eventBus);
115 }
116}
117
ANSWER
Answered 2021-Nov-25 at 16:54Answering my own question.
Instead of using event.getCategory().equals(SomeBiomeCategory)
in the if
statement in the OreGen
class you should use event.getName().equals(YourModBiomeInit.BiomeName.getId()
. Because event.getCategory().equals(SomeBiomeCategory)
gets the category of the biome currently generating whilst event.getName().equals(YourModBiomeInit.BiomeName.getId()
gets the registered name (or id).
So the if statement would look something like this :
1public class OreGeneration
2{
3 public static void generateOres(final BiomeLoadingEvent event)
4 {
5 // Gigalium :
6 if(!(event.getCategory().equals(Biome.Category.THEEND)))
7 {
8 // Nether :
9 if(event.getCategory().equals(Biome.Category.NETHER))
10 {
11 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NETHERRACK, BlockInit.GIGALIUM_NETHER_ORE.get().defaultBlockState(), 6, 25, 50, 2);
12 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NETHERRACK, BlockInit.GIGALIUM_NETHER_ORE.get().defaultBlockState(), 4, 51, 120, 2);
13 }
14
15 // Overworld :
16 if(event.getCategory().equals(Biome.Category.SWAMP) || event.getCategory().equals(Biome.Category.TAIGA))
17 {
18 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 5, 12, 15, 2);
19 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 4, 16, 20, 2);
20 }
21
22 if(!(event.getCategory().equals(Biome.Category.SWAMP) && event.getCategory().equals(Biome.Category.TAIGA)))
23 {
24 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 4, 10, 13, 1);
25 generateOre(event.getGeneration(), OreFeatureConfig.FillerBlockType.NATURAL_STONE, BlockInit.GIGALIUM_ORE.get().defaultBlockState(), 3, 14, 18, 1);
26 }
27 }
28 }
29
30 private static void generateOre(BiomeGenerationSettingsBuilder settings, RuleTest fillerType, BlockState state, int veinSize, int minHeight, int maxHeight, int amount)
31 {
32 settings.addFeature(GenerationStage.Decoration.UNDERGROUND_ORES, Feature.ORE.configured(new OreFeatureConfig(fillerType, state, veinSize)).decorated(Placement.RANGE.configured(new TopSolidRangeConfig(minHeight, 0, maxHeight))).squared().count(amount));
33 }
34}
35{
36 "type": "gigawhat_gigamod:gigaland",
37 "generator": {
38 "type": "minecraft:noise",
39 "seed": 0,
40 "settings": {
41 "bedrock_roof_position": -10,
42 "bedrock_floor_position": 0,
43 "sea_level": 80,
44 "disable_mob_generation": true,
45 "default_block": {
46 "Name": "gigawhat_gigamod:gigastone"
47 },
48 "default_fluid": {
49 "Name": "minecraft:water",
50 "Properties": {
51 "level": "0"
52 }
53 },
54 "noise": {
55 "height": 256,
56 "density_factor": 1,
57 "density_offset": -0.46875,
58 "size_horizontal": 1,
59 "size_vertical": 2,
60 "simplex_surface_noise": true,
61 "random_density_offset": true,
62 "amplified": true,
63 "sampling": {
64 "xz_scale": 1,
65 "y_scale": 1,
66 "xz_factor": 80,
67 "y_factor": 160
68 },
69 "bottom_slide": {
70 "target": -30,
71 "size": 0,
72 "offset": 0
73 },
74 "top_slide": {
75 "target": -10,
76 "size": 3,
77 "offset": 0
78 }
79 },
80 "structures": {
81 "structures": {}
82 }
83 },
84 "biome_source": {
85 "type": "minecraft:fixed",
86 "biome": "gigawhat_gigamod:gigaland_main_biome"
87 }
88 }
89}
90public class ModBiomes
91{
92 public static final DeferredRegister<Biome> BIOMES = DeferredRegister.create(ForgeRegistries.BIOMES, Gigamod.MOD_ID);
93
94 public static final RegistryObject<Biome> GIGALAND_MAIN_BIOME = BIOMES.register("gigaland_main_biome", () -> makeGigalandMainBiome(() -> ModConfiguredSurfaceBuilders.GIGALAND_SURFACE, 0.205f, 0.02f));
95
96 private static Biome makeGigalandMainBiome(final Supplier<ConfiguredSurfaceBuilder<?>> surfaceBuilder, float depth, float scale)
97 {
98 MobSpawnInfo.Builder mobspawninfo$builder = new MobSpawnInfo.Builder();
99 BiomeGenerationSettings.Builder biomegenerationsettings$builder = (new BiomeGenerationSettings.Builder()).surfaceBuilder(surfaceBuilder);
100
101 DefaultBiomeFeatures.addDefaultOverworldLandStructures(biomegenerationsettings$builder);
102 biomegenerationsettings$builder.addStructureStart(StructureFeatures.MINESHAFT);
103
104 DefaultBiomeFeatures.addDefaultCarvers(biomegenerationsettings$builder);
105 DefaultBiomeFeatures.addDefaultUndergroundVariety(biomegenerationsettings$builder);
106
107 mobspawninfo$builder.addSpawn(EntityClassification.MONSTER, new MobSpawnInfo.Spawners(EntityType.BLAZE, 100, 10, 15));
108
109 return (new Biome.Builder()).precipitation(RainType.RAIN).biomeCategory(Category.EXTREME_HILLS).depth(depth).scale(scale).temperature(1.5F).downfall(0.9F).specialEffects((new BiomeAmbience.Builder()).waterColor(65518).waterFogColor(16763760).fogColor(16763760).skyColor(16763760).foliageColorOverride(9547008).grassColorOverride(9547008).ambientParticle(new ParticleEffectAmbience(ParticleTypes.LAVA, 0.003f)).skyColor(16763760).ambientLoopSound(SoundEvents.AMBIENT_CRIMSON_FOREST_LOOP).ambientMoodSound(new MoodSoundAmbience(SoundEvents.AMBIENT_WARPED_FOREST_MOOD, 6000, 8, 2.0D)).ambientAdditionsSound(new SoundAdditionsAmbience(SoundEvents.AMBIENT_NETHER_WASTES_MOOD, 0.0111D)).build()).mobSpawnSettings(mobspawninfo$builder.build()).generationSettings(biomegenerationsettings$builder.build()).build();
110 }
111
112 public static void register(IEventBus eventBus)
113 {
114 BIOMES.register(eventBus);
115 }
116}
117if(event.getName().equals(YourModBiomeInit.SOME_BIOME.getId()))
118{
119 // Generate ores ...
120}
121
QUESTION
Special condition - remove all the version numbers from the mods to search for the new version
Asked 2021-Oct-29 at 17:19Trying to create an update script for Minecraft mods and need to be able to remove all the version numbers from the mods to search for the new version.
I have gotten it working to a point but am stuck on one last part. I cannot get it to leave out the 25 from pre25 from that line I need cfm pre (the 25 is the build number which I do not want)
1[A-Za-z].*?(?=-[0-9])|(?<= ).*(?= )|([s].*?[k])|([f].*?[e])
2
1[A-Za-z].*?(?=-[0-9])|(?<= ).*(?= )|([s].*?[k])|([f].*?[e])
21.17.1-additionalbars-2.1.0.jar
3'[1.17.1] SecurityCraft v1.8.23-beta5.jar'
4absentbydesign-1.17.1-1.6.0.jar
5additionalbarsbop-2.1.0.jar
6AdditionalEnchantedMiner-1.17-17.6-SNAPSHOT.jar
7additionallanterns-1.0.0a-mc1.17.jar
8cfm-7.0.0pre25-1.17.1.jar
9Croptopia-1.17-FORGE-1.6.2.jar
10nekoration-1.17.X-1.4.0.jar
11ScalableCatsForce-2.13.6-build-4-with-library.jar
12spark-forge.jar
13treeharvester_1.17.1-3.2.jar
14
ANSWER
Answered 2021-Oct-29 at 13:46This part in your pattern is matching too much, as this part .*?(?=-[0-9])
is matching as least as possible chars until it can assert -[0-9]
to the right which will match pre25 in pre25-1
You could update the pattern to match an optional part matching digits separated by dots, and in the positive lookahead add asserting optional digits at the beginning [A-Za-z_]+(?:\d+(?:\.\d+)+)?(?=[0-9]*-[0-9])
to reach the hyphen followed by a digit.
You could make the .*?
non greedy matching all between spaces as .*
can over match in case of more spaces.
The updated pattern (without the capture groups if you want a match only) could look like
1[A-Za-z].*?(?=-[0-9])|(?<= ).*(?= )|([s].*?[k])|([f].*?[e])
21.17.1-additionalbars-2.1.0.jar
3'[1.17.1] SecurityCraft v1.8.23-beta5.jar'
4absentbydesign-1.17.1-1.6.0.jar
5additionalbarsbop-2.1.0.jar
6AdditionalEnchantedMiner-1.17-17.6-SNAPSHOT.jar
7additionallanterns-1.0.0a-mc1.17.jar
8cfm-7.0.0pre25-1.17.1.jar
9Croptopia-1.17-FORGE-1.6.2.jar
10nekoration-1.17.X-1.4.0.jar
11ScalableCatsForce-2.13.6-build-4-with-library.jar
12spark-forge.jar
13treeharvester_1.17.1-3.2.jar
14[A-Za-z_]+(?:\d+(?:\.\d+)+)?(?=[0-9]*-[0-9])|(?<= ).*?(?= )|s.*?k|f.*?e
15
QUESTION
How to filter an array on click in react?
Asked 2021-Oct-05 at 23:48So, basically, I'm making a website where you can search for Minecraft hacked clients. There is a search bar on the website, but you have to search in exact terms (different topic lol). Basically on the click of a button (search button) I then want to filter using the search term, (not automatically as I have it now) I've been searching but cant find a way to do it.
Code ->
1import CountUp from 'react-countup';
2import { Link } from 'react-router-dom';
3import '../App.css';
4
5/*Components ->*/
6import Client from '../components/client.js'
7
8function App() {
9
10 const [search, setSearch] = React.useState({
11 searchname: ''
12 });
13
14 **Array containing client data ->** const [client, setClient] = React.useState([
15 { safestatus: 'safe-status-green', safe: 'Safe (Verified)', name: 'Impact', price: 'Free', mcversion: '1.11.2 - 1.16.5', type: 'Injected', compat: 'None (Stand alone client)', desc: 'The Impact client is an advanced utility mod for Minecraft, it is packaged with Baritone and includes a large number of useful mods.', screen: 'https://impactclient.net/', download: 'https://impactclient.net/'},
16 { safestatus: 'safe-status-green', safe: 'Safe (Verified)', name: 'Future', price: '15€', mcversion: '1.8.9 - 1.14.4', type: 'Injected', compat: 'None (Stand alone client)', desc: 'Vanilla, OptiFine, Forge and Liteloader support, Easy to use account manager, Auto-reconnect mod.', screen: 'https://www.futureclient.net/', download: 'https://www.futureclient.net/'}
17
18 ]);
19
20 const updateSearch = (event) => {
21 event.persist();
22 setSearch((prev) => ({
23 ...prev,
24 [event.target.name]: event.target.value
25 }));
26 };
27
28 return (
29 <body>
30 <div className='header'><Link to='/'>Hacked Hub</Link><div className='header-links'><Link to='/about-us'>About Us</Link> | <Link to='/faq'>FAQ</Link></div></div>
31 <div className='counter'><CountUp end={16} duration={0.5}></CountUp>+</div>
32 <div className='counter-desc'><div className='code'>hacked clients</div> and counting...</div>
33 <div className='nxt-tab'>
34 <input name='searchname' value={search.searchname} onChange={updateSearch} placeholder='Search'></input>
35 <select name='price'>
36 <option value='Free'>Free</option>
37 <option value='Paid'>Paid</option>
38 </select>
39 <select name='safe'>
40 <option value='Safe'>Safe</option>
41 <option value='Probably Safe'>Probably Safe</option>
42 <option value='Not Safe'>Not Safe (BE CAREFUL!)</option>
43 </select>
44 <select name='mcver'>
45 <option value='1.8.9'>1.8.9</option>
46 <option value='1.12.2'>1.12.2</option>
47 <option value='1.16.5'>1.16.5</option>
48 <option value='1.17+'>1.17+</option>
49 </select>
50 <select name='type'>
51 <option value='Main'>Injected</option>
52 <option value='Side'>Mod</option>
53 </select>
54 <select name='compatibility'>
55 <option value='With Most Other Clients'>With Most Other Clients</option>
56 <option value='Stand Alone'>Stand Alone</option>
57 </select>
58 <div className='client-warning'><div className='safe-status-red'><div className='code'>⚠ WARNING ⚠</div></div> Only download clients you know are <div className='code'>100%</div> safe! If we do find a client that is a <div className='code'>rat / virus / BTC miner</div> we will tag it as <div className='safe-status-red'><div className='code'>UNSAFE IMMEDIATELY</div></div>. The saftey warnings for clients are <div className='code'>MERE RECCOMENDATIONS</div>, please do thorough research before downloading any hacked client that you are not <div className='code'>100%</div> sure is safe. This page is also in <div className='code'>development</div>, meaning features are prone to break! So be careful!!!</div>
59 <div className='code'>Sponsored clients</div>
60 <h1>None XD</h1>
61 <div className='code'>Submitted clients</div>
62 {client
63 **Filtering the array then mapping it -> (This i want to do onClick)** .filter((client) => client.name === search.searchname)
64 .map((client, index) => {
65 return (
66 <Client
67 safestatus={client.safestatus}
68 safe={client.safe}
69 name={client.name}
70 price={client.price}
71 mcversion={client.mcversion}
72 type={client.type}
73 compat={client.compat}
74 desc={client.desc}
75 screen={client.screen}
76 download={client.download}
77 />
78 );
79 })}
80 </div>
81 </body>
82 );
83}
84
85export default App;
86
Anyone know how I could do this onClick?
ANSWER
Answered 2021-Oct-05 at 23:48Use two pieces of state; one to track the value in your text field and the other to store the search term for filtering. Only set the latter when you click your button
1import CountUp from 'react-countup';
2import { Link } from 'react-router-dom';
3import '../App.css';
4
5/*Components ->*/
6import Client from '../components/client.js'
7
8function App() {
9
10 const [search, setSearch] = React.useState({
11 searchname: ''
12 });
13
14 **Array containing client data ->** const [client, setClient] = React.useState([
15 { safestatus: 'safe-status-green', safe: 'Safe (Verified)', name: 'Impact', price: 'Free', mcversion: '1.11.2 - 1.16.5', type: 'Injected', compat: 'None (Stand alone client)', desc: 'The Impact client is an advanced utility mod for Minecraft, it is packaged with Baritone and includes a large number of useful mods.', screen: 'https://impactclient.net/', download: 'https://impactclient.net/'},
16 { safestatus: 'safe-status-green', safe: 'Safe (Verified)', name: 'Future', price: '15€', mcversion: '1.8.9 - 1.14.4', type: 'Injected', compat: 'None (Stand alone client)', desc: 'Vanilla, OptiFine, Forge and Liteloader support, Easy to use account manager, Auto-reconnect mod.', screen: 'https://www.futureclient.net/', download: 'https://www.futureclient.net/'}
17
18 ]);
19
20 const updateSearch = (event) => {
21 event.persist();
22 setSearch((prev) => ({
23 ...prev,
24 [event.target.name]: event.target.value
25 }));
26 };
27
28 return (
29 <body>
30 <div className='header'><Link to='/'>Hacked Hub</Link><div className='header-links'><Link to='/about-us'>About Us</Link> | <Link to='/faq'>FAQ</Link></div></div>
31 <div className='counter'><CountUp end={16} duration={0.5}></CountUp>+</div>
32 <div className='counter-desc'><div className='code'>hacked clients</div> and counting...</div>
33 <div className='nxt-tab'>
34 <input name='searchname' value={search.searchname} onChange={updateSearch} placeholder='Search'></input>
35 <select name='price'>
36 <option value='Free'>Free</option>
37 <option value='Paid'>Paid</option>
38 </select>
39 <select name='safe'>
40 <option value='Safe'>Safe</option>
41 <option value='Probably Safe'>Probably Safe</option>
42 <option value='Not Safe'>Not Safe (BE CAREFUL!)</option>
43 </select>
44 <select name='mcver'>
45 <option value='1.8.9'>1.8.9</option>
46 <option value='1.12.2'>1.12.2</option>
47 <option value='1.16.5'>1.16.5</option>
48 <option value='1.17+'>1.17+</option>
49 </select>
50 <select name='type'>
51 <option value='Main'>Injected</option>
52 <option value='Side'>Mod</option>
53 </select>
54 <select name='compatibility'>
55 <option value='With Most Other Clients'>With Most Other Clients</option>
56 <option value='Stand Alone'>Stand Alone</option>
57 </select>
58 <div className='client-warning'><div className='safe-status-red'><div className='code'>⚠ WARNING ⚠</div></div> Only download clients you know are <div className='code'>100%</div> safe! If we do find a client that is a <div className='code'>rat / virus / BTC miner</div> we will tag it as <div className='safe-status-red'><div className='code'>UNSAFE IMMEDIATELY</div></div>. The saftey warnings for clients are <div className='code'>MERE RECCOMENDATIONS</div>, please do thorough research before downloading any hacked client that you are not <div className='code'>100%</div> sure is safe. This page is also in <div className='code'>development</div>, meaning features are prone to break! So be careful!!!</div>
59 <div className='code'>Sponsored clients</div>
60 <h1>None XD</h1>
61 <div className='code'>Submitted clients</div>
62 {client
63 **Filtering the array then mapping it -> (This i want to do onClick)** .filter((client) => client.name === search.searchname)
64 .map((client, index) => {
65 return (
66 <Client
67 safestatus={client.safestatus}
68 safe={client.safe}
69 name={client.name}
70 price={client.price}
71 mcversion={client.mcversion}
72 type={client.type}
73 compat={client.compat}
74 desc={client.desc}
75 screen={client.screen}
76 download={client.download}
77 />
78 );
79 })}
80 </div>
81 </body>
82 );
83}
84
85export default App;
86const [ searchValue, setSearchValue ] = React.useState("")
87const [ searchTerm, setSearchTerm ] = React.useState("")
88
89const filteredClient = React.useMemo(() => {
90 if (searchTerm.length > 0) {
91 return client.filter(({ name }) => name === searchTerm)
92 }
93 return client
94}, [ searchTerm, client ])
95
and in your JSX
1import CountUp from 'react-countup';
2import { Link } from 'react-router-dom';
3import '../App.css';
4
5/*Components ->*/
6import Client from '../components/client.js'
7
8function App() {
9
10 const [search, setSearch] = React.useState({
11 searchname: ''
12 });
13
14 **Array containing client data ->** const [client, setClient] = React.useState([
15 { safestatus: 'safe-status-green', safe: 'Safe (Verified)', name: 'Impact', price: 'Free', mcversion: '1.11.2 - 1.16.5', type: 'Injected', compat: 'None (Stand alone client)', desc: 'The Impact client is an advanced utility mod for Minecraft, it is packaged with Baritone and includes a large number of useful mods.', screen: 'https://impactclient.net/', download: 'https://impactclient.net/'},
16 { safestatus: 'safe-status-green', safe: 'Safe (Verified)', name: 'Future', price: '15€', mcversion: '1.8.9 - 1.14.4', type: 'Injected', compat: 'None (Stand alone client)', desc: 'Vanilla, OptiFine, Forge and Liteloader support, Easy to use account manager, Auto-reconnect mod.', screen: 'https://www.futureclient.net/', download: 'https://www.futureclient.net/'}
17
18 ]);
19
20 const updateSearch = (event) => {
21 event.persist();
22 setSearch((prev) => ({
23 ...prev,
24 [event.target.name]: event.target.value
25 }));
26 };
27
28 return (
29 <body>
30 <div className='header'><Link to='/'>Hacked Hub</Link><div className='header-links'><Link to='/about-us'>About Us</Link> | <Link to='/faq'>FAQ</Link></div></div>
31 <div className='counter'><CountUp end={16} duration={0.5}></CountUp>+</div>
32 <div className='counter-desc'><div className='code'>hacked clients</div> and counting...</div>
33 <div className='nxt-tab'>
34 <input name='searchname' value={search.searchname} onChange={updateSearch} placeholder='Search'></input>
35 <select name='price'>
36 <option value='Free'>Free</option>
37 <option value='Paid'>Paid</option>
38 </select>
39 <select name='safe'>
40 <option value='Safe'>Safe</option>
41 <option value='Probably Safe'>Probably Safe</option>
42 <option value='Not Safe'>Not Safe (BE CAREFUL!)</option>
43 </select>
44 <select name='mcver'>
45 <option value='1.8.9'>1.8.9</option>
46 <option value='1.12.2'>1.12.2</option>
47 <option value='1.16.5'>1.16.5</option>
48 <option value='1.17+'>1.17+</option>
49 </select>
50 <select name='type'>
51 <option value='Main'>Injected</option>
52 <option value='Side'>Mod</option>
53 </select>
54 <select name='compatibility'>
55 <option value='With Most Other Clients'>With Most Other Clients</option>
56 <option value='Stand Alone'>Stand Alone</option>
57 </select>
58 <div className='client-warning'><div className='safe-status-red'><div className='code'>⚠ WARNING ⚠</div></div> Only download clients you know are <div className='code'>100%</div> safe! If we do find a client that is a <div className='code'>rat / virus / BTC miner</div> we will tag it as <div className='safe-status-red'><div className='code'>UNSAFE IMMEDIATELY</div></div>. The saftey warnings for clients are <div className='code'>MERE RECCOMENDATIONS</div>, please do thorough research before downloading any hacked client that you are not <div className='code'>100%</div> sure is safe. This page is also in <div className='code'>development</div>, meaning features are prone to break! So be careful!!!</div>
59 <div className='code'>Sponsored clients</div>
60 <h1>None XD</h1>
61 <div className='code'>Submitted clients</div>
62 {client
63 **Filtering the array then mapping it -> (This i want to do onClick)** .filter((client) => client.name === search.searchname)
64 .map((client, index) => {
65 return (
66 <Client
67 safestatus={client.safestatus}
68 safe={client.safe}
69 name={client.name}
70 price={client.price}
71 mcversion={client.mcversion}
72 type={client.type}
73 compat={client.compat}
74 desc={client.desc}
75 screen={client.screen}
76 download={client.download}
77 />
78 );
79 })}
80 </div>
81 </body>
82 );
83}
84
85export default App;
86const [ searchValue, setSearchValue ] = React.useState("")
87const [ searchTerm, setSearchTerm ] = React.useState("")
88
89const filteredClient = React.useMemo(() => {
90 if (searchTerm.length > 0) {
91 return client.filter(({ name }) => name === searchTerm)
92 }
93 return client
94}, [ searchTerm, client ])
95<input
96 name="searchname"
97 placeholder="Search"
98 value={searchValue}
99 onChange={e => setSearchValue(e.target.value)}
100/>
101
102<!-- snip -->
103
104<button
105 type="button"
106 onClick={() => setSearchTerm(searchValue)}
107>Search</button>
108
109<!-- snip -->
110
111{filteredClient.map((client, index) => (
112 <Client .../>
113))}
114
Community Discussions contain sources that include Stack Exchange Network