mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 18:34:56 -04:00
Merge branch 'development' into render
# Conflicts: # pom.xml # src/main/java/de/bixilon/minosoft/data/world/BlockPosition.java # src/main/java/de/bixilon/minosoft/data/world/Chunk.java # src/main/java/de/bixilon/minosoft/data/world/ChunkSection.java # src/main/java/de/bixilon/minosoft/data/world/InChunkLocation.java # src/main/java/de/bixilon/minosoft/data/world/World.java # src/main/java/de/bixilon/minosoft/util/ChunkUtil.java
This commit is contained in:
commit
f79b438108
@ -2,7 +2,7 @@ variables:
|
||||
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
|
||||
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
|
||||
|
||||
image: maven:3-openjdk-14
|
||||
image: maven:3-openjdk-15
|
||||
|
||||
cache:
|
||||
paths:
|
||||
@ -14,4 +14,4 @@ stages:
|
||||
verify:
|
||||
stage: verify
|
||||
script:
|
||||
- 'mvn $MAVEN_CLI_OPTS verify'
|
||||
- 'mvn $MAVEN_CLI_OPTS verify'
|
||||
|
1
.idea/compiler.xml
generated
1
.idea/compiler.xml
generated
@ -10,5 +10,6 @@
|
||||
<module name="Minosoft" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
<bytecodeTargetLevel target="15" />
|
||||
</component>
|
||||
</project>
|
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -8,7 +8,7 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_14" default="false" project-jdk-name="14" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_14_PREVIEW" default="false" project-jdk-name="15" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
13
ReadMe.md
13
ReadMe.md
@ -24,8 +24,8 @@ Minosoft is an open source minecraft client, written from scratch in java. It ai
|
||||
- Disk space: Minosoft itself is pretty small (2-3 Mib), the libraries are a bit bigger (up to 100 Mib).
|
||||
You also need to have the "normal" minecraft assets (~ 300 Mib). So a total of 500 Mib is recommended.
|
||||
- GPU: Currently only needed for rendering, no clue yet.
|
||||
- Java 14 (This is really important, we use specific features that are only available in the latest version. Java 8 is **not** supported).
|
||||
OpenJDK 14 is (of course) also supported.
|
||||
- Java 15 (This is really important, we use specific features that are only available in the latest version. Java 8 is **not** supported).
|
||||
OpenJDK 15 is (of course) also supported.
|
||||
|
||||
|
||||
## Rendering
|
||||
@ -69,4 +69,13 @@ Many thanks to [Credits](Credits.md).
|
||||
## Releases and beta
|
||||
We are almost ready to release a beta once !8 is merged.
|
||||
|
||||
## Compiling and running
|
||||
1. Install Maven and java 15 (On Ubuntu based distributions: `sudo apt install maven openjdk-15-jdk`)
|
||||
2. Clone this repo (`git clone https://gitlab.bixilon.de/bixilon/minosoft.git`)
|
||||
3. Change directory (`cd minosoft`)
|
||||
4. Checkout the branch (`git checkout <branch>`). Probably `render`
|
||||
5. Run Minosoft with `mvn javafx:run`. If any errors occur, feel free to open an issue. In this early stage it might be helpful
|
||||
to delete the app data folder (only of minosoft).
|
||||
|
||||
|
||||
This readme is work in progress, things may change over time.
|
||||
|
@ -12,6 +12,7 @@ In the root folder of your jar file (the mod) must be a file called `mod.json`.
|
||||
"Example dev"
|
||||
],
|
||||
"name": "Example Mod",
|
||||
"moddingAPIVersion": 1,
|
||||
"identifier": "example",
|
||||
"mainClass": "de.example.mod.Main",
|
||||
"loading": {
|
||||
@ -43,7 +44,8 @@ In the root folder of your jar file (the mod) must be a file called `mod.json`.
|
||||
- `uuid` is a unique id for the mod. Generate 1 and keep it in all versions (used for dependencies, etc). **Required**
|
||||
- `versionId` like in android there is a numeric version id. It is used to compare between versions (and as identifier). **Required**
|
||||
- `versionName`, `authors`, `name` is the classic implementation of metadata. Can be anything, will be displayed in the mod list. **Required**
|
||||
- `identifier` is the prefix of items (for Minecraft it is `minecraft`). Aka the thing before the ``. **Required**
|
||||
- `moddingAPIVersion` Modding API version of minosoft. Currently `1` **Required**
|
||||
- `identifier` is the prefix of items (for Minecraft it is `minecraft`). Aka the thing before the `:`. **Required**
|
||||
- `mainClass` the Main class of your mod (self explaining). The main class needs to extent the abstract class `MinosoftMod`. **Required**
|
||||
- `loading` Loading attributes. **Optional**
|
||||
- `priority` should the mod be loaded at the beginning or at the end. Possible values are `LOWEST`, `LOW`, `NORMAL`, `HIGH`, `HIGHEST` **Optional**
|
||||
@ -52,8 +54,8 @@ In the root folder of your jar file (the mod) must be a file called `mod.json`.
|
||||
- `soft` These mods are **optional** to work. Both use the following format: **Optional**
|
||||
- `uuid` the uuid of the mod to load. **Required**
|
||||
- `version` Specifies the version you need to load. **Optional**
|
||||
- `minimum` Minimum versionId required. **Maximum, minimum or both**
|
||||
- `maximum` Maximum versionId required. **Maximum, minimum or both**
|
||||
- `minimum` Minimum versionId required. **Maximum, minimum, both or none**
|
||||
- `maximum` Maximum versionId required. **Maximum, minimum, both or none**
|
||||
|
||||
## Mod loading (aka Main class)
|
||||
Your main class must extend the following class: `de.bixilon.minosoft.MinosoftMod`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
before_install:
|
||||
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
|
||||
- source install-jdk.sh --feature 14
|
||||
- jshell --version
|
||||
- source install-jdk.sh --feature 15
|
||||
- jshell --version
|
||||
|
13
pom.xml
13
pom.xml
@ -24,8 +24,9 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>14</source>
|
||||
<target>14</target>
|
||||
<source>15</source>
|
||||
<target>15</target>
|
||||
<compilerArgs>--enable-preview</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@ -37,9 +38,7 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>
|
||||
org.apache.maven.plugins
|
||||
</groupId>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<configuration>
|
||||
@ -57,8 +56,8 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>14</maven.compiler.source>
|
||||
<maven.compiler.target>14</maven.compiler.target>
|
||||
<maven.compiler.source>15</maven.compiler.source>
|
||||
<maven.compiler.target>15</maven.compiler.target>
|
||||
<lwjgl.version>3.2.3</lwjgl.version>
|
||||
</properties>
|
||||
|
||||
|
@ -33,19 +33,19 @@ public class Configuration {
|
||||
private final Object lock = new Object();
|
||||
|
||||
public Configuration() throws IOException {
|
||||
File file = new File(StaticConfiguration.homeDir + "config/" + StaticConfiguration.CONFIG_FILENAME);
|
||||
File file = new File(StaticConfiguration.HOME_DIR + "config/" + StaticConfiguration.CONFIG_FILENAME);
|
||||
if (!file.exists()) {
|
||||
// no configuration file
|
||||
InputStream input = getClass().getResourceAsStream("/config/" + StaticConfiguration.CONFIG_FILENAME);
|
||||
if (input == null) {
|
||||
throw new FileNotFoundException(String.format("[Config] Missing default config: %s!", StaticConfiguration.CONFIG_FILENAME));
|
||||
}
|
||||
File folder = new File(StaticConfiguration.homeDir + "config/");
|
||||
File folder = new File(StaticConfiguration.HOME_DIR + "config/");
|
||||
if (!folder.exists() && !folder.mkdirs()) {
|
||||
throw new IOException("[Config] Could not create config folder!");
|
||||
}
|
||||
Files.copy(input, Paths.get(file.getAbsolutePath()));
|
||||
file = new File(StaticConfiguration.homeDir + "config/" + StaticConfiguration.CONFIG_FILENAME);
|
||||
file = new File(StaticConfiguration.HOME_DIR + "config/" + StaticConfiguration.CONFIG_FILENAME);
|
||||
}
|
||||
config = Util.readJsonFromFile(file.getAbsolutePath());
|
||||
int configVersion = getInt(ConfigurationPaths.CONFIG_VERSION);
|
||||
@ -67,7 +67,7 @@ public class Configuration {
|
||||
}
|
||||
}
|
||||
// write config to temp file, delete original config, rename temp file to original file to avoid conflicts if minosoft gets closed while saving the config
|
||||
File tempFile = new File(StaticConfiguration.homeDir + "config/" + StaticConfiguration.CONFIG_FILENAME + ".tmp");
|
||||
File tempFile = new File(StaticConfiguration.HOME_DIR + "config/" + StaticConfiguration.CONFIG_FILENAME + ".tmp");
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
FileWriter writer;
|
||||
try {
|
||||
|
@ -23,10 +23,11 @@ public class StaticConfiguration {
|
||||
public static final boolean COLORED_LOG = true; // the log should be colored with ANSI (does not affect base components)
|
||||
public static final boolean LOG_RELATIVE_TIME = false; // prefix all log messages with the relative start time in milliseconds instead of the formatted time
|
||||
|
||||
public static String homeDir;
|
||||
public static final String HOME_DIR;
|
||||
|
||||
static {
|
||||
// Sets Config.homeDir to the correct folder per OS
|
||||
String homeDir;
|
||||
homeDir = System.getProperty("user.home");
|
||||
if (!homeDir.endsWith(File.separator)) {
|
||||
homeDir += "/";
|
||||
@ -42,5 +43,6 @@ public class StaticConfiguration {
|
||||
// failed creating folder
|
||||
throw new RuntimeException(String.format("Could not create home folder (%s)!", homeDir));
|
||||
}
|
||||
HOME_DIR = folder.getAbsolutePath() + "/";
|
||||
}
|
||||
}
|
||||
|
@ -13,22 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data;
|
||||
|
||||
public class EntityRotation {
|
||||
final float yaw;
|
||||
final float pitch;
|
||||
final float roll;
|
||||
|
||||
public EntityRotation(float yaw, float pitch, float roll) {
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.roll = roll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s %s", getYaw(), getPitch(), getRoll());
|
||||
}
|
||||
|
||||
public record EntityRotation(float yaw, float pitch, float roll) {
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
@ -40,4 +25,9 @@ public class EntityRotation {
|
||||
public float getRoll() {
|
||||
return roll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s %s", yaw, pitch, roll);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class Player {
|
||||
public final HashMap<UUID, PlayerListItem> playerList = new HashMap<>();
|
||||
final MojangAccount account;
|
||||
final ScoreboardManager scoreboardManager = new ScoreboardManager();
|
||||
final World world = new World("world");
|
||||
final World world = new World();
|
||||
final HashMap<Integer, Inventory> inventories = new HashMap<>();
|
||||
float health;
|
||||
int food;
|
||||
|
@ -13,26 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data;
|
||||
|
||||
public class Vector {
|
||||
final int x;
|
||||
final int y;
|
||||
final int z;
|
||||
|
||||
public Vector(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
Vector pos = (Vector) obj;
|
||||
return pos.getX() == getX() && pos.getY() == getY() && pos.getZ() == getZ();
|
||||
}
|
||||
|
||||
public record Vector(int x, int y, int z) {
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
@ -47,6 +28,6 @@ public class Vector {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s %s", getX(), getY(), getZ());
|
||||
return String.format("%s %s %s", x, y, z);
|
||||
}
|
||||
}
|
||||
|
@ -249,6 +249,6 @@ public class AssetsManager {
|
||||
}
|
||||
|
||||
private static String getAssetDiskPath(String hash) {
|
||||
return StaticConfiguration.homeDir + String.format("assets/objects/%s/%s.gz", hash.substring(0, 2), hash);
|
||||
return StaticConfiguration.HOME_DIR + String.format("assets/objects/%s/%s.gz", hash.substring(0, 2), hash);
|
||||
}
|
||||
}
|
||||
|
@ -13,32 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Location {
|
||||
final double x;
|
||||
final double y;
|
||||
final double z;
|
||||
|
||||
public Location(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
Location that = (Location) obj;
|
||||
return that.getX() == getX() && that.getY() == getY() && that.getZ() == getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
public record Location(double x, double y, double z) {
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
@ -54,6 +29,6 @@ public class Location {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s %s", getX(), getY(), getZ());
|
||||
return String.format("%s %s %s", x, y, z);
|
||||
}
|
||||
}
|
||||
|
@ -13,33 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class RelativeLocation {
|
||||
final double x;
|
||||
final double y;
|
||||
final double z;
|
||||
|
||||
public RelativeLocation(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
RelativeLocation that = (RelativeLocation) obj;
|
||||
return that.getX() == getX() && that.getY() == getY() && that.getZ() == getZ();
|
||||
}
|
||||
|
||||
public record RelativeLocation(double x, double y, double z) {
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
@ -54,6 +28,6 @@ public class RelativeLocation {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s %s", getX(), getY(), getZ());
|
||||
return String.format("%s %s %s", x, y, z);
|
||||
}
|
||||
}
|
||||
|
@ -15,17 +15,7 @@ package de.bixilon.minosoft.data.entities;
|
||||
|
||||
import de.bixilon.minosoft.data.mappings.MobEffect;
|
||||
|
||||
public class StatusEffect {
|
||||
final MobEffect effect;
|
||||
final int amplifier;
|
||||
final int duration;
|
||||
|
||||
public StatusEffect(MobEffect effect, int amplifier, int duration) {
|
||||
this.effect = effect;
|
||||
this.amplifier = amplifier;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public record StatusEffect(MobEffect effect, int amplifier, int duration) {
|
||||
public int getAmplifier() {
|
||||
return amplifier;
|
||||
}
|
||||
|
@ -13,26 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.entities;
|
||||
|
||||
public class Velocity {
|
||||
final short x;
|
||||
final short y;
|
||||
final short z;
|
||||
|
||||
public Velocity(short x, short y, short z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
Velocity that = (Velocity) obj;
|
||||
return that.getX() == getX() && that.getY() == getY() && that.getZ() == getZ();
|
||||
}
|
||||
|
||||
public record Velocity(short x, short y, short z) {
|
||||
public short getX() {
|
||||
return x;
|
||||
}
|
||||
@ -47,6 +28,6 @@ public class Velocity {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s %s", getX(), getY(), getZ());
|
||||
return String.format("%s %s %s", x, y, z);
|
||||
}
|
||||
}
|
||||
|
@ -16,38 +16,9 @@ package de.bixilon.minosoft.data.entities;
|
||||
import de.bixilon.minosoft.data.MapSet;
|
||||
import de.bixilon.minosoft.data.VersionValueMap;
|
||||
|
||||
public class VillagerData {
|
||||
final VillagerTypes type;
|
||||
final VillagerProfessions profession;
|
||||
final VillagerLevels level;
|
||||
|
||||
public record VillagerData(VillagerTypes type, VillagerProfessions profession, VillagerLevels level) {
|
||||
public VillagerData(int type, int profession, int level, int versionId) {
|
||||
this.type = VillagerTypes.byId(type);
|
||||
this.profession = VillagerProfessions.byId(profession, versionId);
|
||||
this.level = VillagerLevels.byId(level);
|
||||
}
|
||||
|
||||
public VillagerData(VillagerTypes type, VillagerProfessions profession, VillagerLevels level) {
|
||||
this.type = type;
|
||||
this.profession = profession;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return type.hashCode() * profession.hashCode() * level.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
if (hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
VillagerData their = (VillagerData) obj;
|
||||
return getType() == their.getType() && getProfession() == their.getProfession() && getLevel() == their.getLevel();
|
||||
this(VillagerTypes.byId(type), VillagerProfessions.byId(profession, versionId), VillagerLevels.byId(level));
|
||||
}
|
||||
|
||||
public VillagerTypes getType() {
|
||||
|
@ -26,9 +26,9 @@ public class BedEntityMetaData extends BlockEntityMetaData {
|
||||
}
|
||||
|
||||
public BedEntityMetaData(NBTTag nbt) {
|
||||
if (nbt instanceof StringTag) {
|
||||
if (nbt instanceof StringTag stringTag) {
|
||||
// yes, we support bed rgb colors :D
|
||||
color = new RGBColor(((StringTag) nbt).getValue());
|
||||
color = new RGBColor(stringTag.getValue());
|
||||
return;
|
||||
}
|
||||
color = switch (((IntTag) nbt).getValue()) {
|
||||
|
@ -309,8 +309,8 @@ public class EntityMetaData {
|
||||
|
||||
public boolean getBoolean(int index, boolean defaultValue) {
|
||||
Object ret = get(index, defaultValue);
|
||||
if (ret instanceof Byte) {
|
||||
return (byte) ret == 0x01;
|
||||
if (ret instanceof Byte b) {
|
||||
return b == 0x01;
|
||||
}
|
||||
return (boolean) get(index, defaultValue);
|
||||
}
|
||||
|
@ -13,15 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.mappings;
|
||||
|
||||
public class BlockId {
|
||||
final String mod;
|
||||
final String identifier;
|
||||
|
||||
public BlockId(String mod, String identifier) {
|
||||
this.mod = mod;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public record BlockId(String mod, String identifier) {
|
||||
public String getMod() {
|
||||
return mod;
|
||||
}
|
||||
@ -34,21 +26,4 @@ public class BlockId {
|
||||
public String toString() {
|
||||
return String.format("%s:%s", getMod(), getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mod.hashCode() * identifier.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
if (hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
BlockId their = (BlockId) obj;
|
||||
return getIdentifier().equals(their.getIdentifier()) && getMod().equals(their.getMod());
|
||||
}
|
||||
}
|
||||
|
@ -13,42 +13,17 @@
|
||||
|
||||
package de.bixilon.minosoft.data.mappings;
|
||||
|
||||
public class Enchantment {
|
||||
final String mod;
|
||||
final String identifier;
|
||||
|
||||
public Enchantment(String mod, String identifier) {
|
||||
this.mod = mod;
|
||||
this.identifier = identifier;
|
||||
public record Enchantment(String mod, String identifier) {
|
||||
public String getMod() {
|
||||
return mod;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public String getMod() {
|
||||
return mod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s:%s", getMod(), getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mod.hashCode() * identifier.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
if (hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
Enchantment their = (Enchantment) obj;
|
||||
return getIdentifier().equals(their.getIdentifier()) && getMod().equals(their.getMod());
|
||||
return String.format("%s:%s", mod, identifier);
|
||||
}
|
||||
}
|
||||
|
@ -13,15 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.mappings;
|
||||
|
||||
public class MobEffect {
|
||||
final String mod;
|
||||
final String identifier;
|
||||
|
||||
public MobEffect(String mod, String identifier) {
|
||||
this.mod = mod;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public record MobEffect(String mod, String identifier) {
|
||||
public String getMod() {
|
||||
return mod;
|
||||
}
|
||||
@ -34,21 +26,4 @@ public class MobEffect {
|
||||
public String toString() {
|
||||
return String.format("%s:%s", getMod(), getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mod.hashCode() * identifier.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
if (hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
MobEffect their = (MobEffect) obj;
|
||||
return getIdentifier().equals(their.getIdentifier()) && getMod().equals(their.getMod());
|
||||
}
|
||||
}
|
||||
|
@ -13,15 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.mappings;
|
||||
|
||||
public class Motive {
|
||||
final String mod;
|
||||
final String identifier;
|
||||
|
||||
public Motive(String mod, String identifier) {
|
||||
this.mod = mod;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public record Motive(String mod, String identifier) {
|
||||
public String getMod() {
|
||||
return mod;
|
||||
}
|
||||
@ -34,21 +26,4 @@ public class Motive {
|
||||
public String toString() {
|
||||
return String.format("%s:%s", getMod(), getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mod.hashCode() * identifier.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
if (hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
Motive their = (Motive) obj;
|
||||
return getIdentifier().equals(their.getIdentifier()) && getMod().equals(their.getMod());
|
||||
}
|
||||
}
|
||||
|
@ -13,15 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.mappings.particle;
|
||||
|
||||
public class Particle {
|
||||
final String mod;
|
||||
final String identifier;
|
||||
|
||||
public Particle(String mod, String identifier) {
|
||||
this.mod = mod;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public record Particle(String mod, String identifier) {
|
||||
public String getMod() {
|
||||
return mod;
|
||||
}
|
||||
@ -32,23 +24,6 @@ public class Particle {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s:%s", getMod(), getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mod.hashCode() * identifier.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
if (hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
Particle their = (Particle) obj;
|
||||
return getIdentifier().equals(their.getIdentifier()) && getMod().equals(their.getMod());
|
||||
return String.format("%s:%s", mod, identifier);
|
||||
}
|
||||
}
|
||||
|
@ -15,14 +15,9 @@ package de.bixilon.minosoft.data.mappings.recipes;
|
||||
|
||||
import de.bixilon.minosoft.data.inventory.Slot;
|
||||
|
||||
public class Ingredient {
|
||||
final Slot[] slot;
|
||||
|
||||
public Ingredient(Slot[] slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public record Ingredient(Slot[] slot) {
|
||||
public static boolean slotEquals(Slot[] one, Slot[] two) {
|
||||
// ToDo
|
||||
if (one.length != two.length) {
|
||||
return false;
|
||||
}
|
||||
@ -43,18 +38,6 @@ public class Ingredient {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
if (this.hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
Ingredient their = (Ingredient) obj;
|
||||
return slotEquals(getSlot(), their.getSlot());
|
||||
}
|
||||
|
||||
public Slot[] getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
@ -13,15 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.mappings.statistics;
|
||||
|
||||
public class Statistic {
|
||||
final String mod;
|
||||
final String identifier;
|
||||
|
||||
public Statistic(String mod, String identifier) {
|
||||
this.mod = mod;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public record Statistic(String mod, String identifier) {
|
||||
public String getMod() {
|
||||
return mod;
|
||||
}
|
||||
@ -32,22 +24,6 @@ public class Statistic {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s:%s", getMod(), getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mod.hashCode() * identifier.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
if (hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
return toString().equals(obj.toString());
|
||||
return String.format("%s:%s", mod, identifier);
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ public class Versions {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// check if mapping folder exist
|
||||
File mappingFolder = new File(StaticConfiguration.homeDir + "assets/mapping");
|
||||
File mappingFolder = new File(StaticConfiguration.HOME_DIR + "assets/mapping");
|
||||
if (!mappingFolder.exists()) {
|
||||
if (mappingFolder.mkdirs()) {
|
||||
Log.verbose("Created mappings folder.");
|
||||
@ -138,7 +138,7 @@ public class Versions {
|
||||
}
|
||||
}
|
||||
|
||||
String fileName = StaticConfiguration.homeDir + String.format("assets/mapping/%s.tar.gz", version.getVersionName());
|
||||
String fileName = StaticConfiguration.HOME_DIR + String.format("assets/mapping/%s.tar.gz", version.getVersionName());
|
||||
HashMap<String, JsonObject> files;
|
||||
try {
|
||||
files = Util.readJsonTarGzFile(fileName);
|
||||
|
@ -16,29 +16,17 @@ package de.bixilon.minosoft.data.world;
|
||||
import de.bixilon.minosoft.render.blockModels.Face.RenderConstants;
|
||||
import de.bixilon.minosoft.render.utility.Vec3;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class BlockPosition {
|
||||
final int x;
|
||||
final int y;
|
||||
final int z;
|
||||
|
||||
public BlockPosition(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
public record BlockPosition(int x, int y, int z) {
|
||||
public BlockPosition(Vec3 vec3) {
|
||||
this((int) vec3.x, (int) vec3.y, (int) vec3.z);
|
||||
}
|
||||
|
||||
public BlockPosition(Vec3 testPosition) {
|
||||
x = (int) testPosition.x;
|
||||
y = (short) testPosition.y;
|
||||
z = (int) testPosition.z;
|
||||
public BlockPosition(ChunkLocation chunkLocation, Byte height, InChunkSectionLocation sectionLocation) {
|
||||
this((chunkLocation.getX() * RenderConstants.SECTION_WIDTH + sectionLocation.getX()), (chunkLocation.getX() * RenderConstants.SECTION_WIDTH + sectionLocation.getX()), (chunkLocation.getZ() * RenderConstants.SECTION_WIDTH + sectionLocation.getZ()));
|
||||
}
|
||||
|
||||
public BlockPosition(ChunkLocation chunkLocation, Byte height, ChunkNibbleLocation nibbleLocation) {
|
||||
this.x = chunkLocation.getX() * RenderConstants.SECTION_WIDTH + nibbleLocation.getX();
|
||||
this.y = height * RenderConstants.SECTION_HEIGHT + nibbleLocation.getY();
|
||||
this.z = chunkLocation.getZ() * RenderConstants.SECTION_WIDTH + nibbleLocation.getZ();
|
||||
public ChunkLocation getChunkLocation() {
|
||||
return new ChunkLocation(x / 16, z / 16);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
@ -53,48 +41,21 @@ public class BlockPosition {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
public InChunkLocation getInChunkLocation() {
|
||||
int x = this.x % RenderConstants.SECTION_WIDTH;
|
||||
if (x < 0) {
|
||||
x += RenderConstants.SECTION_WIDTH;
|
||||
}
|
||||
BlockPosition pos = (BlockPosition) obj;
|
||||
return pos.getX() == getX() && pos.getY() == getY() && pos.getZ() == getZ();
|
||||
}
|
||||
|
||||
public ChunkLocation getChunkLocation() {
|
||||
int x = getX() / RenderConstants.SECTION_WIDTH;
|
||||
int z = getZ() / RenderConstants.SECTION_WIDTH;
|
||||
//ToDo
|
||||
if (getX() < 0) {
|
||||
x--;
|
||||
int z = this.z % RenderConstants.SECTION_WIDTH;
|
||||
if (z < 0) {
|
||||
z += RenderConstants.SECTION_WIDTH;
|
||||
}
|
||||
if (getZ() < 0) {
|
||||
z--;
|
||||
}
|
||||
return new ChunkLocation(x, z);
|
||||
return new InChunkLocation(x, this.y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%d %d %d", getX(), getY(), getZ());
|
||||
}
|
||||
|
||||
public InChunkLocation getInChunkLocation() {
|
||||
int x = getX() % RenderConstants.SECTION_WIDTH;
|
||||
if (x < 0) {
|
||||
x += RenderConstants.SECTION_WIDTH;
|
||||
}
|
||||
int z = getZ() % RenderConstants.SECTION_WIDTH;
|
||||
if (z < 0) {
|
||||
z += RenderConstants.SECTION_WIDTH;
|
||||
}
|
||||
return new InChunkLocation(x, getY(), z);
|
||||
return String.format("%d %d %d", x, y, z);
|
||||
}
|
||||
|
||||
public BlockPosition add(int[] ints) {
|
||||
|
@ -21,13 +21,13 @@ import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Collection of 16 chunks nibbles
|
||||
* Collection of 16 chunks sections
|
||||
*/
|
||||
public class Chunk {
|
||||
final ConcurrentHashMap<Byte, ChunkNibble> nibbles;
|
||||
final ConcurrentHashMap<Byte, ChunkSection> sections;
|
||||
|
||||
public Chunk(ConcurrentHashMap<Byte, ChunkNibble> chunks) {
|
||||
this.nibbles = chunks;
|
||||
public Chunk(ConcurrentHashMap<Byte, ChunkSection> sections) {
|
||||
this.sections = sections;
|
||||
}
|
||||
|
||||
public Block getBlock(InChunkLocation location) {
|
||||
@ -36,27 +36,27 @@ public class Chunk {
|
||||
|
||||
public Block getBlock(int x, int y, int z) {
|
||||
byte section = (byte) (y / RenderConstants.SECTION_HEIGHT);
|
||||
if (!nibbles.containsKey(section)) {
|
||||
if (!sections.containsKey(section)) {
|
||||
return Blocks.nullBlock;
|
||||
}
|
||||
return nibbles.get(section).getBlock(x, y % RenderConstants.SECTION_HEIGHT, z);
|
||||
return sections.get(section).getBlock(x, y % RenderConstants.SECTION_HEIGHT, z);
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, Block block) {
|
||||
byte section = (byte) (y / RenderConstants.SECTION_HEIGHT);
|
||||
createSectionIfNotExists(section);
|
||||
nibbles.get(section).setBlock(x, y % RenderConstants.SECTION_HEIGHT, z, block);
|
||||
sections.get(section).setBlock(x, y % RenderConstants.SECTION_HEIGHT, z, block);
|
||||
}
|
||||
|
||||
public void setBlock(InChunkLocation location, Block block) {
|
||||
byte section = (byte) (location.getY() / RenderConstants.SECTION_HEIGHT);
|
||||
createSectionIfNotExists(section);
|
||||
nibbles.get(section).setBlock(location.getChunkNibbleLocation(), block);
|
||||
sections.get(section).setBlock(location.getInChunkSectionLocation(), block);
|
||||
}
|
||||
|
||||
void createSectionIfNotExists(byte section) {
|
||||
if (nibbles.get(section) == null) {
|
||||
nibbles.put(section, new ChunkNibble());
|
||||
if (sections.get(section) == null) {
|
||||
sections.put(section, new ChunkSection());
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ public class Chunk {
|
||||
blocks.forEach(this::setBlock);
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<Byte, ChunkNibble> getNibbles() {
|
||||
return nibbles;
|
||||
public ConcurrentHashMap<Byte, ChunkSection> getSections() {
|
||||
return sections;
|
||||
}
|
||||
}
|
||||
|
@ -13,34 +13,10 @@
|
||||
|
||||
package de.bixilon.minosoft.data.world;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Chunk X and Z location (block position / 16, rounded down)
|
||||
*/
|
||||
public class ChunkLocation {
|
||||
final int x;
|
||||
final int z;
|
||||
|
||||
public ChunkLocation(int x, int z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
ChunkLocation that = (ChunkLocation) obj;
|
||||
return getX() == that.getX() && getZ() == that.getZ();
|
||||
}
|
||||
|
||||
public record ChunkLocation(int x, int z) {
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
@ -51,6 +27,6 @@ public class ChunkLocation {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%d %d", getX(), getZ());
|
||||
return String.format("%d %d", x, z);
|
||||
}
|
||||
}
|
||||
|
@ -21,31 +21,30 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
/**
|
||||
* Collection of 16x16x16 blocks
|
||||
*/
|
||||
public class ChunkNibble {
|
||||
final ConcurrentHashMap<ChunkNibbleLocation, Block> blocks;
|
||||
public class ChunkSection {
|
||||
final ConcurrentHashMap<InChunkSectionLocation, Block> blocks;
|
||||
|
||||
public ChunkNibble(ConcurrentHashMap<ChunkNibbleLocation, Block> blocks) {
|
||||
public ChunkSection(ConcurrentHashMap<InChunkSectionLocation, Block> blocks) {
|
||||
this.blocks = blocks;
|
||||
}
|
||||
|
||||
public ChunkNibble() {
|
||||
// empty
|
||||
public ChunkSection() {
|
||||
this.blocks = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public Block getBlock(int x, int y, int z) {
|
||||
return getBlock(new ChunkNibbleLocation(x, y, z));
|
||||
return getBlock(new InChunkSectionLocation(x, y, z));
|
||||
}
|
||||
|
||||
public Block getBlock(ChunkNibbleLocation loc) {
|
||||
public Block getBlock(InChunkSectionLocation loc) {
|
||||
return blocks.get(loc);
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, Block block) {
|
||||
setBlock(new ChunkNibbleLocation(x, y, z), block);
|
||||
setBlock(new InChunkSectionLocation(x, y, z), block);
|
||||
}
|
||||
|
||||
public void setBlock(ChunkNibbleLocation location, Block block) {
|
||||
public void setBlock(InChunkSectionLocation location, Block block) {
|
||||
if (block == null || block.equals(Blocks.nullBlock)) {
|
||||
blocks.remove(location);
|
||||
return;
|
||||
@ -53,7 +52,7 @@ public class ChunkNibble {
|
||||
blocks.put(location, block);
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<ChunkNibbleLocation, Block> getBlocks() {
|
||||
public ConcurrentHashMap<InChunkSectionLocation, Block> getBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
}
|
@ -15,31 +15,14 @@ package de.bixilon.minosoft.data.world;
|
||||
|
||||
import de.bixilon.minosoft.render.blockModels.Face.RenderConstants;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class InChunkLocation {
|
||||
final int x;
|
||||
final int y;
|
||||
final int z;
|
||||
|
||||
public InChunkLocation(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
/**
|
||||
* Chunk X, Y and Z location (max 16x255x16)
|
||||
*/
|
||||
public record InChunkLocation(int x, int y, int z) {
|
||||
public InChunkLocation {
|
||||
if (x > 15 || y > 255 || z > 15 || x < 0 || y < 0 || z < 0) {
|
||||
throw new IllegalArgumentException(String.format("Invalid chunk location %s %s %s", x, y, z));
|
||||
}
|
||||
InChunkLocation that = (InChunkLocation) obj;
|
||||
return getX() == that.getX() && getY() == that.getY() && getZ() == that.getZ();
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
@ -50,16 +33,16 @@ public class InChunkLocation {
|
||||
return y;
|
||||
}
|
||||
|
||||
public ChunkNibbleLocation getChunkNibbleLocation() {
|
||||
return new ChunkNibbleLocation(getX(), getY() % RenderConstants.SECTION_HEIGHT, getZ());
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public InChunkSectionLocation getInChunkSectionLocation() {
|
||||
return new InChunkSectionLocation(x, y % RenderConstants.SECTION_HEIGHT, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%d %d %d", getX(), getY(), getZ());
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
return String.format("%d %d %d", x, y, z);
|
||||
}
|
||||
}
|
||||
|
@ -13,36 +13,10 @@
|
||||
|
||||
package de.bixilon.minosoft.data.world;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Chunk X, Y and Z location (max 16x16x16)
|
||||
*/
|
||||
public class ChunkNibbleLocation {
|
||||
final int x;
|
||||
final int y;
|
||||
final int z;
|
||||
|
||||
public ChunkNibbleLocation(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
ChunkNibbleLocation that = (ChunkNibbleLocation) obj;
|
||||
return getX() == that.getX() && getY() == that.getY() && getZ() == that.getZ();
|
||||
}
|
||||
|
||||
public record InChunkSectionLocation(int x, int y, int z) {
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
@ -57,6 +31,6 @@ public class ChunkNibbleLocation {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%d %d %d", getX(), getY(), getZ());
|
||||
return String.format("%d %d %d", x, y, z);
|
||||
}
|
||||
}
|
@ -23,35 +23,22 @@ import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Collection of ChunkColumns
|
||||
* Collection of chunks
|
||||
*/
|
||||
public class World {
|
||||
final ConcurrentHashMap<ChunkLocation, Chunk> chunks = new ConcurrentHashMap<>();
|
||||
final ConcurrentHashMap<Integer, Entity> entities = new ConcurrentHashMap<>();
|
||||
final String name;
|
||||
final HashMap<BlockPosition, BlockEntityMetaData> blockEntityMeta = new HashMap<>();
|
||||
boolean hardcore;
|
||||
boolean raining;
|
||||
Dimension dimension; // used for sky color, etc
|
||||
|
||||
public World(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Chunk getChunk(ChunkLocation loc) {
|
||||
return chunks.get(loc);
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<ChunkLocation, Chunk> getAllChunks() {
|
||||
return chunks;
|
||||
}
|
||||
|
||||
public Block getBlock(BlockPosition pos) {
|
||||
if (pos.y < 1) {
|
||||
if (pos.getY() < 1) {
|
||||
return Blocks.nullBlock;
|
||||
}
|
||||
ChunkLocation loc = pos.getChunkLocation();
|
||||
@ -133,4 +120,8 @@ public class World {
|
||||
public void setBlockEntityData(HashMap<BlockPosition, BlockEntityMetaData> blockEntities) {
|
||||
blockEntities.forEach(blockEntityMeta::put);
|
||||
}
|
||||
|
||||
public Chunk getChunk(ChunkLocation chunkLocation) {
|
||||
return chunks.get(chunkLocation);
|
||||
}
|
||||
}
|
||||
|
@ -421,9 +421,8 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
||||
grid.add(new Label(LocaleManager.translate(Strings.SERVER_INFO_SERVER_MODDED_BRAND) + ":"), 0, ++column);
|
||||
grid.add(moddedBrandLabel, 1, column);
|
||||
|
||||
if (lastPing.getServerModInfo() instanceof ForgeModInfo) {
|
||||
ForgeModInfo modInfo = (ForgeModInfo) lastPing.getServerModInfo();
|
||||
Label moddedModsLabel = new Label(modInfo.getModList().toString());
|
||||
if (lastPing.getServerModInfo() instanceof ForgeModInfo forgeModInfo) {
|
||||
Label moddedModsLabel = new Label(forgeModInfo.getModList().toString());
|
||||
moddedModsLabel.setWrapText(true);
|
||||
|
||||
grid.add(new Label(LocaleManager.translate(Strings.SERVER_INFO_SERVER_MODDED_MOD_LIST) + ":"), 0, ++column);
|
||||
|
@ -43,7 +43,7 @@ public class EventMethod {
|
||||
if (!method.getParameters()[0].getType().isAssignableFrom(event.getClass())) {
|
||||
return;
|
||||
}
|
||||
if (!annotation.ignoreCancelled() && event instanceof CancelableEvent && ((CancelableEvent) event).isCancelled()) {
|
||||
if (!annotation.ignoreCancelled() && event instanceof CancelableEvent cancelableEvent && cancelableEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.modding.loading;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import de.bixilon.minosoft.util.Util;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ModDependency {
|
||||
|
||||
private final UUID uuid;
|
||||
private Integer versionMinimum;
|
||||
private Integer versionMaximum;
|
||||
|
||||
public ModDependency(UUID uuid, Integer versionMinimum, Integer versionMaximum) {
|
||||
this.uuid = uuid;
|
||||
this.versionMinimum = versionMinimum;
|
||||
this.versionMaximum = versionMaximum;
|
||||
}
|
||||
|
||||
public ModDependency(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public static ModDependency serialize(JsonObject json) {
|
||||
UUID uuid = Util.getUUIDFromString(json.get("uuid").getAsString());
|
||||
Integer versionMinimum = null;
|
||||
Integer versionMaximum = null;
|
||||
|
||||
if (json.has("version")) {
|
||||
JsonObject version = json.getAsJsonObject("version");
|
||||
if (version.has("minimum")) {
|
||||
versionMinimum = version.get("minimum").getAsInt();
|
||||
}
|
||||
if (version.has("maximum")) {
|
||||
versionMaximum = version.get("maximum").getAsInt();
|
||||
}
|
||||
}
|
||||
return new ModDependency(uuid, versionMinimum, versionMaximum);
|
||||
}
|
||||
|
||||
public static HashSet<ModDependency> serializeDependencyArray(JsonArray json) {
|
||||
HashSet<ModDependency> result = new HashSet<>();
|
||||
json.forEach((jsonElement -> result.add(serialize(jsonElement.getAsJsonObject()))));
|
||||
return result;
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public Integer getVersionMinimum() {
|
||||
return versionMinimum;
|
||||
}
|
||||
|
||||
public Integer getVersionMaximum() {
|
||||
return versionMaximum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = uuid.hashCode();
|
||||
if (versionMinimum != null && versionMinimum > 0) {
|
||||
result *= versionMinimum;
|
||||
}
|
||||
|
||||
if (versionMaximum != null && versionMaximum > 0) {
|
||||
result *= versionMaximum;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
if (hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
ModDependency their = (ModDependency) obj;
|
||||
return getUUID().equals(their.getUUID()) && getVersionMaximum().equals(their.getVersionMaximum()) && getVersionMinimum().equals(their.getVersionMinimum());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String result = uuid.toString();
|
||||
if (versionMinimum != null) {
|
||||
result += " >" + versionMinimum;
|
||||
}
|
||||
if (versionMaximum != null) {
|
||||
result += " <" + versionMaximum;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import de.bixilon.minosoft.util.Util;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@ -26,11 +27,14 @@ public class ModInfo {
|
||||
final String versionName;
|
||||
final String name;
|
||||
final String[] authors;
|
||||
final int moddingAPIVersion;
|
||||
final String identifier;
|
||||
final String mainClass;
|
||||
final HashSet<ModDependency> hardDependencies = new HashSet<>();
|
||||
final HashSet<ModDependency> softDependencies = new HashSet<>();
|
||||
LoadingInfo loadingInfo;
|
||||
|
||||
public ModInfo(JsonObject json) {
|
||||
public ModInfo(JsonObject json) throws ModLoadingException {
|
||||
this.uuid = Util.getUUIDFromString(json.get("uuid").getAsString());
|
||||
this.versionId = json.get("versionId").getAsInt();
|
||||
this.versionName = json.get("versionName").getAsString();
|
||||
@ -39,6 +43,10 @@ public class ModInfo {
|
||||
this.authors = new String[authors.size()];
|
||||
AtomicInteger i = new AtomicInteger();
|
||||
authors.forEach((authorElement) -> this.authors[i.getAndIncrement()] = authorElement.getAsString());
|
||||
moddingAPIVersion = json.get("moddingAPIVersion").getAsInt();
|
||||
if (moddingAPIVersion > ModLoader.CURRENT_MODDING_API_VERSION) {
|
||||
throw new ModLoadingException(String.format("Mod was written with for a newer version of minosoft (moddingAPIVersion=%d, expected=%d)", moddingAPIVersion, ModLoader.CURRENT_MODDING_API_VERSION));
|
||||
}
|
||||
this.identifier = json.get("identifier").getAsString();
|
||||
this.mainClass = json.get("mainClass").getAsString();
|
||||
if (json.has("loading")) {
|
||||
@ -48,6 +56,15 @@ public class ModInfo {
|
||||
this.loadingInfo.setLoadingPriority(Priorities.valueOf(loading.get("priority").getAsString()));
|
||||
}
|
||||
}
|
||||
if (json.has("dependencies")) {
|
||||
JsonObject dependencies = json.getAsJsonObject("dependencies");
|
||||
if (dependencies.has("hard")) {
|
||||
hardDependencies.addAll(ModDependency.serializeDependencyArray(dependencies.getAsJsonArray("hard")));
|
||||
}
|
||||
if (dependencies.has("soft")) {
|
||||
softDependencies.addAll(ModDependency.serializeDependencyArray(dependencies.getAsJsonArray("soft")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getAuthors() {
|
||||
|
@ -24,63 +24,78 @@ import org.xeustechnologies.jcl.JclObjectFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class ModLoader {
|
||||
static final LinkedList<MinosoftMod> mods = new LinkedList<>();
|
||||
public static final int CURRENT_MODDING_API_VERSION = 1;
|
||||
public static final LinkedList<MinosoftMod> mods = new LinkedList<>();
|
||||
|
||||
public static void loadMods(CountUpAndDownLatch progress) throws Exception {
|
||||
Log.verbose("Start loading mods...");
|
||||
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), Util.getThreadFactory("ModLoader"));
|
||||
|
||||
// load all jars, parse the mod.json
|
||||
// sort the list and prioritize
|
||||
// load all lists and dependencies async
|
||||
HashSet<Callable<MinosoftMod>> callables = new HashSet<>();
|
||||
File[] files = new File(StaticConfiguration.homeDir + "mods").listFiles();
|
||||
File[] files = new File(StaticConfiguration.HOME_DIR + "mods").listFiles();
|
||||
if (files == null) {
|
||||
// no mods to load
|
||||
return;
|
||||
}
|
||||
CountDownLatch latch = new CountDownLatch(files.length);
|
||||
for (File modFile : files) {
|
||||
if (modFile.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
callables.add(() -> {
|
||||
executor.execute(() -> {
|
||||
MinosoftMod mod = loadMod(progress, modFile);
|
||||
if (mod != null) {
|
||||
mods.add(mod);
|
||||
}
|
||||
return mod;
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
latch.await();
|
||||
|
||||
Util.executeInThreadPool("ModLoader", callables);
|
||||
if (mods.size() == 0) {
|
||||
Log.info("No mods to load.");
|
||||
return;
|
||||
}
|
||||
|
||||
progress.addCount(mods.size() * ModPhases.values().length); // count * mod phases
|
||||
|
||||
// sort for priority
|
||||
mods.sort((a, b) -> {
|
||||
if (a == null || b == null) {
|
||||
return 0;
|
||||
}
|
||||
return -(getLoadingPriorityOrDefault(b.getInfo()).ordinal() - getLoadingPriorityOrDefault(a.getInfo()).ordinal());
|
||||
});
|
||||
// ToDo: check dependencies
|
||||
|
||||
for (ModPhases phase : ModPhases.values()) {
|
||||
Log.verbose(String.format("Map loading phase changed: %s", phase));
|
||||
HashSet<Callable<MinosoftMod>> phaseLoaderCallables = new HashSet<>();
|
||||
mods.forEach((instance) -> phaseLoaderCallables.add(() -> {
|
||||
if (!instance.isEnabled()) {
|
||||
return instance;
|
||||
}
|
||||
if (!instance.start(phase)) {
|
||||
Log.warn(String.format("An error occurred while loading %s", instance.getInfo()));
|
||||
instance.setEnabled(false);
|
||||
}
|
||||
progress.countDown();
|
||||
return instance;
|
||||
}));
|
||||
Util.executeInThreadPool("ModLoader", phaseLoaderCallables);
|
||||
CountDownLatch modLatch = new CountDownLatch(mods.size());
|
||||
mods.forEach((instance) -> {
|
||||
executor.execute(() -> {
|
||||
if (!instance.isEnabled()) {
|
||||
modLatch.countDown();
|
||||
progress.countDown();
|
||||
return;
|
||||
}
|
||||
if (!instance.start(phase)) {
|
||||
Log.warn(String.format("An error occurred while loading %s", instance.getInfo()));
|
||||
instance.setEnabled(false);
|
||||
}
|
||||
modLatch.countDown();
|
||||
progress.countDown();
|
||||
});
|
||||
});
|
||||
modLatch.await();
|
||||
}
|
||||
mods.forEach((instance) -> {
|
||||
if (instance.isEnabled()) {
|
||||
@ -94,6 +109,7 @@ public class ModLoader {
|
||||
}
|
||||
|
||||
public static MinosoftMod loadMod(CountUpAndDownLatch progress, File file) {
|
||||
MinosoftMod instance;
|
||||
try {
|
||||
Log.verbose(String.format("[MOD] Loading file %s", file.getAbsolutePath()));
|
||||
progress.countUp();
|
||||
@ -107,18 +123,17 @@ public class ModLoader {
|
||||
jcl.add(file.getAbsolutePath());
|
||||
JclObjectFactory factory = JclObjectFactory.getInstance();
|
||||
|
||||
MinosoftMod instance = (MinosoftMod) factory.create(jcl, modInfo.getMainClass());
|
||||
instance = (MinosoftMod) factory.create(jcl, modInfo.getMainClass());
|
||||
instance.setInfo(modInfo);
|
||||
Log.verbose(String.format("[MOD] Mod file loaded and added to classpath (%s)", modInfo));
|
||||
zipFile.close();
|
||||
progress.countDown();
|
||||
return instance;
|
||||
} catch (IOException e) {
|
||||
} catch (IOException | ModLoadingException | NullPointerException e) {
|
||||
instance = null;
|
||||
e.printStackTrace();
|
||||
Log.warn(String.format("Could not load mod: %s", file.getAbsolutePath()));
|
||||
}
|
||||
progress.countDown(); // failed
|
||||
return null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static Priorities getLoadingPriorityOrDefault(ModInfo info) {
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.modding.loading;
|
||||
|
||||
public class ModLoadingException extends Exception {
|
||||
public ModLoadingException() {
|
||||
}
|
||||
|
||||
public ModLoadingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ModLoadingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ModLoadingException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public ModLoadingException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
@ -201,8 +201,8 @@ public class Connection {
|
||||
public boolean fireEvent(ConnectionEvent connectionEvent) {
|
||||
Minosoft.eventManagers.forEach((eventManager -> eventManager.getGlobalEventListeners().forEach((method) -> method.invoke(connectionEvent))));
|
||||
eventListeners.forEach((method -> method.invoke(connectionEvent)));
|
||||
if (connectionEvent instanceof CancelableEvent) {
|
||||
return ((CancelableEvent) connectionEvent).isCancelled();
|
||||
if (connectionEvent instanceof CancelableEvent cancelableEvent) {
|
||||
return cancelableEvent.isCancelled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -125,10 +125,9 @@ public class SocketNetwork implements Network {
|
||||
|
||||
outputStream.write(data);
|
||||
outputStream.flush();
|
||||
if (packet instanceof PacketEncryptionResponse) {
|
||||
if (packet instanceof PacketEncryptionResponse packetEncryptionResponse) {
|
||||
// enable encryption
|
||||
secretKey = ((PacketEncryptionResponse) packet).getSecretKey();
|
||||
enableEncryption(secretKey);
|
||||
enableEncryption(packetEncryptionResponse.getSecretKey());
|
||||
// wake up other thread
|
||||
socketRThread.interrupt();
|
||||
}
|
||||
@ -216,8 +215,8 @@ public class SocketNetwork implements Network {
|
||||
//set special settings to avoid miss timing issues
|
||||
if (packetInstance instanceof PacketLoginSuccess) {
|
||||
connection.setConnectionState(ConnectionStates.PLAY);
|
||||
} else if (packetInstance instanceof PacketCompressionInterface) {
|
||||
compressionThreshold = ((PacketCompressionInterface) packetInstance).getThreshold();
|
||||
} else if (packetInstance instanceof PacketCompressionInterface compressionPacket) {
|
||||
compressionThreshold = compressionPacket.getThreshold();
|
||||
} else if (packetInstance instanceof PacketEncryptionRequest) {
|
||||
// wait until response is ready
|
||||
connection.handle(packetInstance);
|
||||
|
@ -55,8 +55,8 @@ public class WorldRenderer {
|
||||
queuedMapData.add(() -> prepareChunk(location, chunk));
|
||||
}
|
||||
|
||||
public void queueChunkNibble(ChunkLocation location, byte sectionHeight, ChunkNibble nibble) {
|
||||
queuedMapData.add(() -> prepareChunkNibble(location, sectionHeight, nibble));
|
||||
public void queueChunkNibble(ChunkLocation location, byte sectionHeight, ChunkSection section) {
|
||||
queuedMapData.add(() -> prepareChunkNibble(location, sectionHeight, section));
|
||||
}
|
||||
|
||||
public void queueBlock(BlockPosition position, Block block) {
|
||||
@ -69,20 +69,20 @@ public class WorldRenderer {
|
||||
private void prepareChunk(ChunkLocation location, Chunk chunk) {
|
||||
// clear or create current chunk
|
||||
ConcurrentHashMap<Byte, ArrayFloatList> chunkFaces = new ConcurrentHashMap<>();
|
||||
chunk.getNibbles().forEach(((height, chunkNibble) -> chunkFaces.put(height, getFacesForChunkNibble(location, height, chunkNibble))));
|
||||
chunk.getSections().forEach(((height, chunkNibble) -> chunkFaces.put(height, getFacesForChunkNibble(location, height, chunkNibble))));
|
||||
faces.put(location, chunkFaces);
|
||||
}
|
||||
|
||||
private void prepareChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkNibble nibble) {
|
||||
faces.get(chunkLocation).put(sectionHeight, getFacesForChunkNibble(chunkLocation, sectionHeight, nibble));
|
||||
private void prepareChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkSection section) {
|
||||
faces.get(chunkLocation).put(sectionHeight, getFacesForChunkNibble(chunkLocation, sectionHeight, section));
|
||||
}
|
||||
|
||||
private ArrayFloatList getFacesForChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkNibble nibble) {
|
||||
private ArrayFloatList getFacesForChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkSection section) {
|
||||
ConcurrentHashMap<ChunkLocation, Chunk> world = connection.getPlayer().getWorld().getAllChunks();
|
||||
// clear or create current chunk nibble
|
||||
ArrayFloatList nibbleMap = new ArrayFloatList();
|
||||
//faces.get(chunkLocation).put(sectionHeight, nibbleMap);
|
||||
ConcurrentHashMap<ChunkNibbleLocation, Block> nibbleBlocks = nibble.getBlocks();
|
||||
ConcurrentHashMap<InChunkSectionLocation, Block> nibbleBlocks = section.getBlocks();
|
||||
nibbleBlocks.forEach((location, block) -> {
|
||||
HashSet<FaceOrientation> facesToDraw = new HashSet<>();
|
||||
|
||||
@ -97,12 +97,12 @@ public class WorldRenderer {
|
||||
}
|
||||
// check if block over us is a full block
|
||||
byte bottomSection = (byte) (sectionHeight - 1);
|
||||
if (!world.get(chunkLocation).getNibbles().containsKey(bottomSection)) {
|
||||
if (!world.get(chunkLocation).getSections().containsKey(bottomSection)) {
|
||||
yield null;
|
||||
}
|
||||
yield world.get(chunkLocation).getNibbles().get(bottomSection).getBlock(location.getX(), RenderConstants.SECTIONS_MAX_Y, location.getZ());
|
||||
yield world.get(chunkLocation).getSections().get(bottomSection).getBlock(location.getX(), RenderConstants.SECTIONS_MAX_Y, location.getZ());
|
||||
}
|
||||
yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY() - 1, location.getZ()));
|
||||
yield nibbleBlocks.get(new InChunkSectionLocation(location.getX(), location.getY() - 1, location.getZ()));
|
||||
}
|
||||
case UP -> {
|
||||
if (location.getY() == RenderConstants.SECTIONS_MAX_Y) {
|
||||
@ -113,48 +113,48 @@ public class WorldRenderer {
|
||||
}
|
||||
// check if block over us is a full block
|
||||
byte upperSection = (byte) (sectionHeight + 1);
|
||||
if (!world.get(chunkLocation).getNibbles().containsKey(upperSection)) {
|
||||
if (!world.get(chunkLocation).getSections().containsKey(upperSection)) {
|
||||
yield null;
|
||||
}
|
||||
yield world.get(chunkLocation).getNibbles().get(upperSection).getBlock(location.getX(), RenderConstants.SECTIONS_MIN_Y, location.getZ());
|
||||
yield world.get(chunkLocation).getSections().get(upperSection).getBlock(location.getX(), RenderConstants.SECTIONS_MIN_Y, location.getZ());
|
||||
}
|
||||
yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY() + 1, location.getZ()));
|
||||
yield nibbleBlocks.get(new InChunkSectionLocation(location.getX(), location.getY() + 1, location.getZ()));
|
||||
}
|
||||
case WEST -> {
|
||||
if (location.getX() == RenderConstants.SECTIONS_MIN_X) {
|
||||
ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX() - 1, chunkLocation.getZ()), sectionHeight);
|
||||
ChunkSection otherChunkNibble = getChunkSectionOfWorld(world, new ChunkLocation(chunkLocation.getX() - 1, chunkLocation.getZ()), sectionHeight);
|
||||
if (otherChunkNibble != null) {
|
||||
yield otherChunkNibble.getBlock(RenderConstants.SECTIONS_MAX_X, location.getY(), location.getZ());
|
||||
}
|
||||
}
|
||||
yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX() - 1, location.getY(), location.getZ()));
|
||||
yield nibbleBlocks.get(new InChunkSectionLocation(location.getX() - 1, location.getY(), location.getZ()));
|
||||
}
|
||||
case EAST -> {
|
||||
if (location.getX() == RenderConstants.SECTIONS_MIN_X) {
|
||||
ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX() + 1, chunkLocation.getZ()), sectionHeight);
|
||||
ChunkSection otherChunkNibble = getChunkSectionOfWorld(world, new ChunkLocation(chunkLocation.getX() + 1, chunkLocation.getZ()), sectionHeight);
|
||||
if (otherChunkNibble != null) {
|
||||
yield otherChunkNibble.getBlock(RenderConstants.SECTIONS_MAX_X, location.getY(), location.getZ());
|
||||
}
|
||||
}
|
||||
yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX() + 1, location.getY(), location.getZ()));
|
||||
yield nibbleBlocks.get(new InChunkSectionLocation(location.getX() + 1, location.getY(), location.getZ()));
|
||||
}
|
||||
case NORTH -> {
|
||||
if (location.getZ() == RenderConstants.SECTIONS_MIN_Z) {
|
||||
ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX(), chunkLocation.getZ() - 1), sectionHeight);
|
||||
ChunkSection otherChunkNibble = getChunkSectionOfWorld(world, new ChunkLocation(chunkLocation.getX(), chunkLocation.getZ() - 1), sectionHeight);
|
||||
if (otherChunkNibble != null) {
|
||||
yield otherChunkNibble.getBlock(location.getX(), location.getY(), RenderConstants.SECTIONS_MAX_Z);
|
||||
}
|
||||
}
|
||||
yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY(), location.getZ() - 1));
|
||||
yield nibbleBlocks.get(new InChunkSectionLocation(location.getX(), location.getY(), location.getZ() - 1));
|
||||
}
|
||||
case SOUTH -> {
|
||||
if (location.getZ() == RenderConstants.SECTIONS_MAX_Z) {
|
||||
ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX(), chunkLocation.getZ() + 1), sectionHeight);
|
||||
ChunkSection otherChunkNibble = getChunkSectionOfWorld(world, new ChunkLocation(chunkLocation.getX(), chunkLocation.getZ() + 1), sectionHeight);
|
||||
if (otherChunkNibble != null) {
|
||||
yield otherChunkNibble.getBlock(location.getX(), location.getY(), RenderConstants.SECTIONS_MIN_Z);
|
||||
}
|
||||
}
|
||||
yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY(), location.getZ() + 1));
|
||||
yield nibbleBlocks.get(new InChunkSectionLocation(location.getX(), location.getY(), location.getZ() + 1));
|
||||
}
|
||||
};
|
||||
if (dependedBlock == null || !BlockModelLoader.getInstance().isFull(dependedBlock, FaceOrientation.inverse(orientation))) {
|
||||
@ -185,9 +185,9 @@ public class WorldRenderer {
|
||||
glEnd();
|
||||
}
|
||||
|
||||
private ChunkNibble getChunkNibbleOfWorld(ConcurrentHashMap<ChunkLocation, Chunk> world, ChunkLocation location, byte sectionHeight) {
|
||||
if (world.containsKey(location) && world.get(location).getNibbles().containsKey(sectionHeight)) {
|
||||
return world.get(location).getNibbles().get(sectionHeight);
|
||||
private ChunkSection getChunkSectionOfWorld(ConcurrentHashMap<ChunkLocation, Chunk> world, ChunkLocation location, byte sectionHeight) {
|
||||
if (world.containsKey(location) && world.get(location).getSections().containsKey(sectionHeight)) {
|
||||
return world.get(location).getSections().get(sectionHeight);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class TextureLoader {
|
||||
}
|
||||
combineTextures();
|
||||
try {
|
||||
PNGDecoder decoder = new PNGDecoder(new FileInputStream(StaticConfiguration.homeDir + "assets/allTextures.png"));
|
||||
PNGDecoder decoder = new PNGDecoder(new FileInputStream(StaticConfiguration.HOME_DIR + "assets/allTextures.png"));
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(decoder.getWidth() * decoder.getHeight() * 4);
|
||||
decoder.decode(buf, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
|
||||
textureID = bindTexture(buf, decoder.getWidth(), decoder.getHeight());
|
||||
@ -118,7 +118,7 @@ public class TextureLoader {
|
||||
}
|
||||
|
||||
try {
|
||||
File outputFile = new File(StaticConfiguration.homeDir + "assets/allTextures.png");
|
||||
File outputFile = new File(StaticConfiguration.HOME_DIR + "assets/allTextures.png");
|
||||
ImageIO.write(totalImage, "png", outputFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -16,8 +16,8 @@ package de.bixilon.minosoft.util;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.Block;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.Blocks;
|
||||
import de.bixilon.minosoft.data.world.Chunk;
|
||||
import de.bixilon.minosoft.data.world.ChunkNibble;
|
||||
import de.bixilon.minosoft.data.world.ChunkNibbleLocation;
|
||||
import de.bixilon.minosoft.data.world.ChunkSection;
|
||||
import de.bixilon.minosoft.data.world.InChunkSectionLocation;
|
||||
import de.bixilon.minosoft.data.world.palette.Palette;
|
||||
import de.bixilon.minosoft.logging.Log;
|
||||
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
|
||||
@ -52,11 +52,11 @@ public final class ChunkUtil {
|
||||
|
||||
//parse data
|
||||
int arrayPos = 0;
|
||||
ConcurrentHashMap<Byte, ChunkNibble> nibbleMap = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<Byte, ChunkSection> sectionMap = new ConcurrentHashMap<>();
|
||||
for (byte c = 0; c < RenderConstants.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column
|
||||
if (BitByte.isBitSet(sectionBitMask, c)) {
|
||||
|
||||
ConcurrentHashMap<ChunkNibbleLocation, Block> blockMap = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<InChunkSectionLocation, Block> blockMap = new ConcurrentHashMap<>();
|
||||
|
||||
for (int nibbleY = 0; nibbleY < RenderConstants.SECTION_HEIGHT; nibbleY++) {
|
||||
for (int nibbleZ = 0; nibbleZ < RenderConstants.SECTION_WIDTH; nibbleZ++) {
|
||||
@ -84,15 +84,15 @@ public final class ChunkUtil {
|
||||
arrayPos++;
|
||||
continue;
|
||||
}
|
||||
blockMap.put(new ChunkNibbleLocation(nibbleX, nibbleY, nibbleZ), block);
|
||||
blockMap.put(new InChunkSectionLocation(nibbleX, nibbleY, nibbleZ), block);
|
||||
arrayPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
nibbleMap.put(c, new ChunkNibble(blockMap));
|
||||
sectionMap.put(c, new ChunkSection(blockMap));
|
||||
}
|
||||
}
|
||||
return new Chunk(nibbleMap);
|
||||
return new Chunk(sectionMap);
|
||||
}
|
||||
if (buffer.getVersionId() < 62) { // ToDo: was this really changed in 62?
|
||||
if (sectionBitMask == 0x00 && groundUpContinuous) {
|
||||
@ -116,12 +116,12 @@ public final class ChunkUtil {
|
||||
}
|
||||
|
||||
int arrayPos = 0;
|
||||
ConcurrentHashMap<Byte, ChunkNibble> nibbleMap = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<Byte, ChunkSection> sectionMap = new ConcurrentHashMap<>();
|
||||
for (byte c = 0; c < RenderConstants.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column
|
||||
if (!BitByte.isBitSet(sectionBitMask, c)) {
|
||||
continue;
|
||||
}
|
||||
ConcurrentHashMap<ChunkNibbleLocation, Block> blockMap = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<InChunkSectionLocation, Block> blockMap = new ConcurrentHashMap<>();
|
||||
|
||||
for (int nibbleY = 0; nibbleY < RenderConstants.SECTION_HEIGHT; nibbleY++) {
|
||||
for (int nibbleZ = 0; nibbleZ < RenderConstants.SECTION_WIDTH; nibbleZ++) {
|
||||
@ -132,17 +132,17 @@ public final class ChunkUtil {
|
||||
arrayPos++;
|
||||
continue;
|
||||
}
|
||||
blockMap.put(new ChunkNibbleLocation(nibbleX, nibbleY, nibbleZ), block);
|
||||
blockMap.put(new InChunkSectionLocation(nibbleX, nibbleY, nibbleZ), block);
|
||||
arrayPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
nibbleMap.put(c, new ChunkNibble(blockMap));
|
||||
sectionMap.put(c, new ChunkSection(blockMap));
|
||||
}
|
||||
return new Chunk(nibbleMap);
|
||||
return new Chunk(sectionMap);
|
||||
}
|
||||
// really big thanks to: https://wiki.vg/index.php?title=Chunk_Format&oldid=13712
|
||||
ConcurrentHashMap<Byte, ChunkNibble> nibbleMap = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<Byte, ChunkSection> sectionMap = new ConcurrentHashMap<>();
|
||||
for (byte c = 0; c < RenderConstants.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column
|
||||
if (!BitByte.isBitSet(sectionBitMask, c)) {
|
||||
continue;
|
||||
@ -156,7 +156,7 @@ public final class ChunkUtil {
|
||||
|
||||
long[] data = buffer.readLongArray(buffer.readVarInt());
|
||||
|
||||
ConcurrentHashMap<ChunkNibbleLocation, Block> blockMap = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<InChunkSectionLocation, Block> blockMap = new ConcurrentHashMap<>();
|
||||
for (int nibbleY = 0; nibbleY < RenderConstants.SECTION_HEIGHT; nibbleY++) {
|
||||
for (int nibbleZ = 0; nibbleZ < RenderConstants.SECTION_WIDTH; nibbleZ++) {
|
||||
for (int nibbleX = 0; nibbleX < RenderConstants.SECTION_WIDTH; nibbleX++) {
|
||||
@ -188,7 +188,7 @@ public final class ChunkUtil {
|
||||
if (block.equals(Blocks.nullBlock)) {
|
||||
continue;
|
||||
}
|
||||
blockMap.put(new ChunkNibbleLocation(nibbleX, nibbleY, nibbleZ), block);
|
||||
blockMap.put(new InChunkSectionLocation(nibbleX, nibbleY, nibbleZ), block);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,12 +200,12 @@ public final class ChunkUtil {
|
||||
}
|
||||
}
|
||||
|
||||
nibbleMap.put(c, new ChunkNibble(blockMap));
|
||||
sectionMap.put(c, new ChunkSection(blockMap));
|
||||
}
|
||||
if (buffer.getVersionId() < 552) {
|
||||
byte[] biomes = buffer.readBytes(RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH);
|
||||
}
|
||||
return new Chunk(nibbleMap);
|
||||
return new Chunk(sectionMap);
|
||||
}
|
||||
|
||||
public static void readSkyLightPacket(InByteBuffer buffer, int skyLightMask, int blockLightMask, int emptyBlockLightMask, int emptySkyLightMask) {
|
||||
|
@ -26,10 +26,9 @@ import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.*;
|
||||
|
||||
@ -246,17 +245,6 @@ public final class Util {
|
||||
return new BufferedInputStream(new URL(url).openStream());
|
||||
}
|
||||
|
||||
public static <T> void executeInThreadPool(String name, Collection<Callable<T>> callables) throws InterruptedException {
|
||||
ExecutorService phaseLoader = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), getThreadFactory(name));
|
||||
phaseLoader.invokeAll(callables).forEach((tFuture -> {
|
||||
try {
|
||||
tFuture.get();
|
||||
} catch (ExecutionException | InterruptedException ex) {
|
||||
ex.getCause().printStackTrace();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static ThreadFactory getThreadFactory(String threadName) {
|
||||
return new ThreadFactoryBuilder().setNameFormat(threadName + "#%d").build();
|
||||
}
|
||||
|
@ -80,9 +80,8 @@ public class CompoundTag extends NBTTag {
|
||||
buffer.writeStringNoLength(set.getKey());
|
||||
|
||||
// write data
|
||||
if (set.getValue() instanceof CompoundTag) {
|
||||
if (set.getValue() instanceof CompoundTag compoundTag) {
|
||||
// that's a subtag! special rule
|
||||
CompoundTag compoundTag = (CompoundTag) set.getValue();
|
||||
compoundTag.writeBytesSubTag(buffer);
|
||||
continue;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user