new block loading system

This commit is contained in:
Lukas 2020-07-28 19:02:28 +02:00
parent 640656a0d7
commit 4046b39d8e
26 changed files with 638 additions and 73 deletions

View File

@ -127,6 +127,12 @@
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>18.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -90,7 +90,6 @@ public class Minosoft {
}
Connection connection = new Connection(config.getString("debug.host"), config.getInteger("debug.port"));
connection.setPlayer(new Player(account));
connection.connect();
MainWindow.start(connection);
}

View File

@ -14,7 +14,6 @@
package de.bixilon.minosoft;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import de.bixilon.minosoft.game.datatypes.TextComponent;
public class ServerListPing {
final JsonObject raw;
@ -46,7 +45,7 @@ public class ServerListPing {
public TextComponent getMotd() {
try {
return new TextComponent(raw.getAsJsonObject("description"));
} catch (JsonParseException ignored) {
} catch (Exception ignored) {
}
return new TextComponent(raw.get("description").getAsString());
}

View File

@ -30,7 +30,7 @@ public class TextComponent {
}
try {
this.json = JsonParser.parseString(raw).getAsJsonObject();
} catch (IllegalStateException e) {
} catch (Exception e) {
// not a text component, is a legacy string
this.json = new JsonObject();
JsonArray extra = new JsonArray();

View File

@ -530,4 +530,8 @@ public class Blocks {
}
return blockId;
}
public static HashSet<Block> getBlockList() {
return blockList;
}
}

View File

@ -194,7 +194,7 @@ public class Network {
e.printStackTrace();
}
} catch (Exception e) {
Log.protocol("Received broken packet!");
Log.info("Received broken packet!");
e.printStackTrace();
}
}

View File

@ -61,7 +61,7 @@ public class PacketHandler {
public void handle(PacketStatusResponse pkg) {
if (connection.getReason() == ConnectionReason.GET_VERSION) {
// now we know the version, set it, if the config allows it
int version = Minosoft.getConfig().getInteger("version");
int version = Minosoft.getConfig().getInteger("debug.version");
if (version == -1) {
connection.setVersion(ProtocolVersion.byId(pkg.getResponse().getProtocolNumber()));
} else {

View File

@ -13,9 +13,9 @@
package de.bixilon.minosoft.render;
import de.bixilon.minosoft.movement.PlayerController;
import de.bixilon.minosoft.protocol.network.Connection;
import de.bixilon.minosoft.render.MainMenu.MainMenu;
import de.bixilon.minosoft.render.movement.PlayerController;
import de.bixilon.minosoft.render.utility.RenderMode;
import static de.bixilon.minosoft.render.utility.RenderMode.MAIN_MENU;
@ -100,7 +100,10 @@ public class MainWindow {
public static void pause() {
renderMode = MAIN_MENU;
glfwSetInputMode(openGLWindow.getWindow(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
connection.disconnect();
try {
connection.disconnect();
} catch (Exception ignored) {
}
}
public static Connection getConnection() {

View File

@ -18,28 +18,28 @@ import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks;
import de.bixilon.minosoft.game.datatypes.world.*;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.render.blockModels.BlockModelLoader;
import de.bixilon.minosoft.render.face.FaceOrientation;
import de.bixilon.minosoft.render.face.FacePosition;
import de.bixilon.minosoft.render.face.RenderConstants;
import de.bixilon.minosoft.render.fullFace.FaceOrientation;
import de.bixilon.minosoft.render.fullFace.FullFacePosition;
import de.bixilon.minosoft.render.fullFace.RenderConstants;
import de.bixilon.minosoft.render.texture.TextureLoader;
import javafx.util.Pair;
import java.util.HashMap;
import java.util.Map;
import static de.bixilon.minosoft.render.face.RenderConstants.UV;
import static de.bixilon.minosoft.render.face.RenderConstants.faceDir;
import static de.bixilon.minosoft.render.fullFace.RenderConstants.UV;
import static de.bixilon.minosoft.render.fullFace.RenderConstants.faceDir;
import static org.lwjgl.opengl.GL11.*;
public class WorldRenderer {
private final TextureLoader textureLoader;
private final HashMap<FacePosition, Pair<Float, Float>> faces;
private final HashMap<FullFacePosition, Pair<Float, Float>> faces;
private final int faceCount = 0;
private BlockModelLoader modelLoader;
public WorldRenderer() {
textureLoader = new TextureLoader(MainWindow.getOpenGLWindow().getWindow());
faces = new HashMap<FacePosition, Pair<Float, Float>>();
faces = new HashMap<FullFacePosition, Pair<Float, Float>>();
}
public void init() {
@ -80,15 +80,15 @@ public class WorldRenderer {
continue;
//TODO: fix buggy behavior, not always working correctly, probably a problem in the World or BlockPosition class
}
FacePosition facePosition = new FacePosition(position, orientation);
Pair<Float, Float> texture = modelLoader.getDrawDescription(block).getTexture(orientation);
/*
FullFacePosition facePosition = new FullFacePosition(position, orientation);
Pair<Float, Float> texture = modelLoader.getBlockDescription(block).getTexture(orientation);
if (!faces.containsKey(facePosition)) {
synchronized (faces) {
faces.put(facePosition, texture);
}
}
*/
}
}
@ -109,7 +109,7 @@ public class WorldRenderer {
glBindTexture(GL_TEXTURE_2D, textureLoader.getTextureID());
glBegin(GL_QUADS);
synchronized (faces) {
for (Map.Entry<FacePosition, Pair<Float, Float>> entry : faces.entrySet()) {
for (Map.Entry<FullFacePosition, Pair<Float, Float>> entry : faces.entrySet()) {
float[][] vertPositions = RenderConstants.FACE_VERTEX[entry.getKey().getFaceOrientation().getId()];
for (int vert = 0; vert < 4; vert++) {

View File

@ -0,0 +1,71 @@
/*
* Codename 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.render.blockModels;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import de.bixilon.minosoft.Config;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import static de.bixilon.minosoft.util.Util.readJsonFromFile;
public class BlockDescription {
HashSet<SubBlock> subBlocks;
boolean isFull;
public BlockDescription(JsonObject json, HashMap<String, String> variables) {
subBlocks = new HashSet<>();
if (!json.has("textures")) {
//throw new IllegalArgumentException("could not find 'textures' in json");
}
try {
JsonObject textures = json.getAsJsonObject("textures");
for (String texture : textures.keySet()) {
if (texture.contains("#") && variables.containsKey(texture)) {
variables.put("#" + texture, variables.get(texture));
} else {
variables.put("#" + texture, textures.get(texture).getAsString());
}
}
} catch (Exception ignored) {
}
if (json.has("elements")) {
for (JsonElement subBlockJson : json.get("elements").getAsJsonArray()) {
subBlocks.add(new SubBlock(subBlockJson.getAsJsonObject(), variables));
}
} else if (json.has("parent") && !json.get("parent").getAsString().equals("block/block")) {
String parent = json.get("parent").getAsString();
String path = Config.homeDir + "assets/minecraft/models/" + parent + ".json";
try {
subBlocks.addAll(new BlockDescription(readJsonFromFile(path), variables).subBlocks);
} catch (IOException e) {
e.printStackTrace();
}
} else {
throw new IllegalArgumentException("json does not have a parent nor subblocks");
}
}
public BlockDescription(JsonObject json) {
this(json, new HashMap<>());
}
public boolean isFull() {
return isFull;
}
}

View File

@ -18,6 +18,7 @@ import de.bixilon.minosoft.Config;
import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block;
import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.BlockProperties;
import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks;
import de.bixilon.minosoft.logging.Log;
import java.io.IOException;
import java.util.HashMap;
@ -25,64 +26,370 @@ import java.util.HashMap;
import static de.bixilon.minosoft.util.Util.readJsonFromFile;
public class BlockModelLoader {
final HashMap<String, DrawDescription> drawDescriptionMap;
final HashMap<String, BlockDescription> blockDescriptionMap;
public BlockModelLoader() {
drawDescriptionMap = new HashMap<>();
try {
loadModels();
} catch (IOException e) {
e.printStackTrace();
}
blockDescriptionMap = new HashMap<>();
loadModels();
}
private void loadModels() throws IOException {
private void loadModels() {
for (Block block : Blocks.getBlockList()) {
String mod = block.getMod();
String identifier = block.getIdentifier();
if (handleProperties(block)) {
return;
}
if (identifier.contains("pane")) {
// TODO: handle glass panes
if (blockDescriptionMap.containsKey(mod + ":" + identifier)) {
continue;
}
if (identifier.equals("large_fern")) {
if (!mod.equals("minecraft")) {
loadModel(mod, identifier);
continue;
}
if (identifier.equals("silver_glazed_terracotta")) {
// WHAT EVEN IS THIS BLOCK!?!?!
continue;
}
if (identifier.equals("flower_upper_block")) {
// WHAT EVEN IS THIS BLOCK!?!?!
continue;
}
if (identifier.equals("bubble_column")) {
// handled with client side particles
continue;
}
if (identifier.equals("barrier")) {
// TODO: display barriers if setting is enabled
continue;
}
if (identifier.equals("shrub")) {
// no longer exists ?
continue;
}
if (identifier.equals("end_portal") || identifier.equals("end_gateway")) {
// TODO: display end portals (the portal itself, not the frames
// probably with a shader
continue;
}
if (identifier.equals("structure_void")) {
// is not displayed
continue;
}
if (identifier.contains("air")) {
// is not displayed
continue;
}
if (identifier.contains("infested")) {
// same block model as the not infested blocks
continue;
}
if (identifier.equals("conduit")) {
// shown as entity?
continue;
}
if (identifier.equals("moving_piston") || identifier.equals("piston_extension")) {
// TODO: handle pistons
continue;
}
if (identifier.contains("skull") || identifier.contains("head")) {
// TODO: handle skulls
continue;
}
if (identifier.equals("water")) {
// TODO: handle water
continue;
}
if (identifier.equals("lava")) {
// TODO: handle lava
continue;
}
if (identifier.contains("chest")) {
// TODO: handle chests (trapped or not)
continue;
}
if (identifier.contains("banner")) {
// TODO: handle banners
continue;
}
if (identifier.contains("shulker_box")) {
// TODO: handle shulker_boxes
continue;
}
if (identifier.contains("sign")) {
// TODO: handle signs
continue;
}
if (identifier.equals("fire")) {
// TODO: handle fire
continue;
}
if (identifier.contains("tripwire_hook")) {
loadModel(mod, identifier);
loadModel(mod, identifier + "_attached");
loadModel(mod, identifier + "_attached_on");
loadModel(mod, identifier + "_on");
continue;
}
if (identifier.contains("brewing_stand")) {
loadModel(mod, identifier);
for (int i = 0; i < 3; i++) {
loadModel(mod, identifier + "_bottle" + i);
loadModel(mod, identifier + "_empty" + i);
}
continue;
}
if (identifier.contains("daylight_detector")) {
loadModel(mod, identifier);
loadModel(mod, identifier + "_inverted");
continue;
}
if (identifier.contains("lever")) {
loadModel(mod, identifier);
loadModel(mod, identifier + "_on");
continue;
}
if (identifier.contains("comparator")) {
loadModel(mod, identifier);
loadModel(mod, identifier + "_on");
loadModel(mod, identifier + "_on_subtract");
loadModel(mod, identifier + "_subtract");
continue;
}
if (identifier.contains("trapdoor")) {
loadModel(mod, identifier + "_bottom");
loadModel(mod, identifier + "_open");
loadModel(mod, identifier + "_top");
continue;
}
if (identifier.contains("pane")) {
loadModel(mod, identifier + "_noside");
loadModel(mod, identifier + "_noside_alt");
loadModel(mod, identifier + "_Post");
loadModel(mod, identifier + "_side");
loadModel(mod, identifier + "_side_alt");
continue;
}
if (identifier.equals("iron_bars")) {
loadModel(mod, identifier + "_cap");
loadModel(mod, identifier + "_cap_alt");
loadModel(mod, identifier + "_post");
loadModel(mod, identifier + "_post_ends");
loadModel(mod, identifier + "_side");
loadModel(mod, identifier + "_side_alt");
continue;
}
if (identifier.endsWith("bed") && !blockDescriptionMap.containsKey(mod + ":bed")) {
// TODO: handle beds
continue;
}
if (identifier.equals("vine")) {
loadModel(mod, identifier + "_1");
loadModel(mod, identifier + "_1u");
loadModel(mod, identifier + "_2");
loadModel(mod, identifier + "_2u");
loadModel(mod, identifier + "_2_opposite");
loadModel(mod, identifier + "_2u_opposite");
loadModel(mod, identifier + "_3");
loadModel(mod, identifier + "_3u");
loadModel(mod, identifier + "_4");
loadModel(mod, identifier + "_4u");
loadModel(mod, identifier + "_u");
continue;
}
if (identifier.equals("tripwire")) {
loadModel(mod, identifier + "_attached_n");
loadModel(mod, identifier + "_attached_ne");
loadModel(mod, identifier + "_attached_ns");
loadModel(mod, identifier + "_attached_nse");
loadModel(mod, identifier + "_attached_nsew");
continue;
}
if (identifier.equals("scaffolding")) {
loadModel(mod, identifier + "_stable");
loadModel(mod, identifier + "_unstable");
continue;
}
if (identifier.equals("bell")) {
loadModel(mod, identifier + "_between_walls");
loadModel(mod, identifier + "_ceiling");
loadModel(mod, identifier + "_floor");
loadModel(mod, identifier + "_wall");
continue;
}
if (identifier.equals("frosted_ice")) {
loadModel(mod, identifier + "_0");
loadModel(mod, identifier + "_1");
loadModel(mod, identifier + "_2");
loadModel(mod, identifier + "_3");
continue;
}
if (identifier.equals("redstone_wire")) {
loadModel(mod, "redstone_dust_dot");
/*
loadModel(mod, "redstone_dust_side");
loadModel(mod, "redstone_dust_side_alt");
loadModel(mod, "redstone_dust_side_alt0");
loadModel(mod, "redstone_dust_side_alt1");
loadModel(mod, "redstone_dust_side0");
loadModel(mod, "redstone_dust_side1");
loadModel(mod, "redstone_dust_up");
*/ // throws error, can't find variable
continue;
}
if (identifier.equals("brown_mushroom_stem")) {
loadModel(mod, "brown_mushroom_block");
continue;
}
if (identifier.equals("red_mushroom_stem")) {
loadModel(mod, "red_mushroom_block");
continue;
}
if (identifier.equals("snow")) {
for (int height = 2; height < 16; height += 2) {
loadModel(mod, identifier + "_height" + height);
}
continue;
}
if (identifier.equals("bamboo")) {
loadModel(mod, identifier + "_large_leaves");
loadModel(mod, identifier + "_sapling");
loadModel(mod, identifier + "_small_leaves");
for (int variation = 1; variation < 5; variation++) {
for (int age = 0; age < 2; age++) {
loadModel(mod, identifier + variation + "_age" + age);
}
}
continue;
}
if (identifier.equals("wheat")) {
for (int stage = 0; stage < 8; stage++) {
loadModel(mod, identifier + "_stage" + stage);
}
continue;
}
if (identifier.equals("potatoes") || identifier.equals("carrots") ||
identifier.equals("beetroots") || identifier.equals("sweet_berry_bush")) {
for (int stage = 0; stage < 4; stage++) {
loadModel(mod, identifier + "_stage" + stage);
}
continue;
}
if (identifier.equals("nether_wart")) {
for (int stage = 0; stage < 3; stage++) {
loadModel(mod, identifier + "_stage" + stage);
}
continue;
}
if (identifier.equals("waterlily")) {
loadModel(mod, "lily_pad");
continue;
}
if (identifier.equals("nether_brick")) {
loadModel(mod, "nether_bricks");
continue;
}
if (identifier.equals("quartz_ore")) {
loadModel(mod, "nether_" + identifier);
continue;
}
if (identifier.contains("end_bricks")) {
loadModel(mod, "end_stone_bricks");
continue;
}
if (identifier.equals("cocoa")) {
for (int stage = 0; stage < 3; stage++) {
loadModel(mod, identifier + "_stage" + stage);
}
continue;
}
if (identifier.equals("melon_stem") || identifier.equals("pumpkin_stem")) {
for (int stage = 0; stage < 8; stage++) {
loadModel(mod, identifier + "_stage" + stage);
}
continue;
}
if (identifier.equals("repeater")) {
loadRepeater(mod, identifier, "1");
loadRepeater(mod, identifier, "2");
loadRepeater(mod, identifier, "3");
loadRepeater(mod, identifier, "4");
continue;
}
if (identifier.contains("door")) {
loadModel(mod, identifier + "_bottom");
loadModel(mod, identifier + "_bottom_hinge");
loadModel(mod, identifier + "_top");
loadModel(mod, identifier + "_top_hinge");
continue;
}
if (identifier.endsWith("wall") || identifier.endsWith("fence")) {
loadModel(mod, identifier + "_inventory");
loadModel(mod, identifier + "_post");
loadModel(mod, identifier + "_side");
continue;
}
if (identifier.contains("large") || identifier.contains("tall") || identifier.equals("sunflower") ||
identifier.equals("rose_bush") || identifier.equals("lilac") || identifier.equals("peony")) {
loadModel(mod, identifier + "_bottom");
loadModel(mod, identifier + "_top");
continue;
}
if (drawDescriptionMap.containsKey((mod + ":" + identifier))) {
// a description for that block already exists, checking because Blocks.getBlockList()
// returns all blocks with all possible combinations
if (identifier.equals("nether_portal")) {
loadModel(mod, identifier + "_ew");
loadModel(mod, identifier + "_ns");
continue;
}
if (identifier.equals("slime")) {
loadModel(mod, identifier + "_block");
continue;
}
loadModel(mod, identifier);
}
Log.info("finished loading all block descriptions");
}
private void loadRepeater(String mod, String identifier, String ticks) {
loadModel(mod, identifier + "_" + ticks + "tick");
loadModel(mod, identifier + "_" + ticks + "tick_locked");
loadModel(mod, identifier + "_" + ticks + "tick_on");
loadModel(mod, identifier + "_" + ticks + "tick_on_locked");
}
private boolean handleProperties(Block block) {
return !block.getProperties().contains(BlockProperties.NONE) && block.getProperties().size() != 0;
}
private void loadModel(String mod, String identifier) throws IOException {
String path = Config.homeDir + "assets/" + mod + "/models/block/" + identifier + ".json";
JsonObject object = readJsonFromFile(path);
DrawDescription description = new DrawDescription(object);
drawDescriptionMap.put(mod + ":" + identifier, description);
private void loadModel(String mod, String identifier) {
if (blockDescriptionMap.containsKey((mod + ":" + identifier))) {
// a description for that block already exists, checking because Blocks.getBlockList()
// returns all blocks with all possible combinations
return;
}
try {
String path = Config.homeDir + "assets/" + mod + "/models/block/" + identifier + ".json";
JsonObject json = readJsonFromFile(path);
BlockDescription description = new BlockDescription(json);
//Log.info("Loaded model for " + mod + ":" + identifier);
} catch (IOException e) {
Log.debug("could not load block model for block " + mod + ":" + identifier);
} catch (Exception e) {
e.printStackTrace();
System.out.println(mod + ":" + identifier);
System.exit(-1);
}
}
public DrawDescription getDrawDescription(Block block) {
if (!drawDescriptionMap.containsKey(block)) {
public BlockDescription getBlockDescription(Block block) {
if (!blockDescriptionMap.containsKey(block)) {
throw new IllegalArgumentException(String.format("No description for block %s found", block));
}
return drawDescriptionMap.get(block.getMod() + ":" + block.getIdentifier());
return blockDescriptionMap.get(block.getMod() + ":" + block.getIdentifier());
}
public boolean isFull(Block block) {
if (block == Blocks.nullBlock || block == null) {
return false;
}
return getDrawDescription(block).isFull();
return getBlockDescription(block).isFull();
}
}
}

View File

@ -1,6 +1,6 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
* Copyright (C) 2020 Lukas Eisenhauer
*
* 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.
*
@ -13,10 +13,6 @@
package de.bixilon.minosoft.render.blockModels;
public enum BlockType {
FULL, // a full block
CUBE_ALL, // a full block but all the sides are the same
HEIGHT, // a full block with a custom y height
STAIRS, // a stairs block
CUSTOM // a unique model not worth having a own type
public interface BlockRenderInterface {
void draw();
}

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.render.blockModels;
import com.google.gson.JsonObject;
import de.bixilon.minosoft.render.MainWindow;
import de.bixilon.minosoft.render.face.FaceOrientation;
import de.bixilon.minosoft.render.fullFace.FaceOrientation;
import javafx.util.Pair;
import java.util.*;

View File

@ -0,0 +1,29 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Lukas Eisenhauer
*
* 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.render.blockModels;
import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block;
import de.bixilon.minosoft.game.datatypes.world.BlockPosition;
import de.bixilon.minosoft.game.datatypes.world.World;
public class FullBlock implements BlockRenderInterface {
public FullBlock(BlockPosition position, Block block, World world) {
}
@Override
public void draw() {
}
}

View File

@ -0,0 +1,84 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Lukas Eisenhauer
*
* 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.render.blockModels;
import com.google.gson.JsonObject;
import de.bixilon.minosoft.render.MainWindow;
import de.bixilon.minosoft.render.fullFace.FaceOrientation;
import de.bixilon.minosoft.render.fullFace.InFaceUV;
import javafx.util.Pair;
import java.util.HashMap;
public class SubBlock {
SubBlockPosition pos1; // the most negative Point of the SubBlock
SubBlockPosition pos2; // the most positive Point of the SubBlock
HashMap<FaceOrientation, Pair<Float, Float>> textures;
HashMap<FaceOrientation, Pair<Float, Float>> cullFaceTextures;
HashMap<FaceOrientation, InFaceUV> uv;
public SubBlock(JsonObject json, HashMap<String, String> variables) {
uv = new HashMap<>();
textures = new HashMap<>();
cullFaceTextures = new HashMap<>();
pos1 = new SubBlockPosition(json.getAsJsonArray("from"));
pos2 = new SubBlockPosition(json.getAsJsonArray("to"));
JsonObject faces = json.getAsJsonObject("faces");
for (FaceOrientation orientation : FaceOrientation.values()) {
if (faces.has(orientation.name().toLowerCase())) {
applyTexture(faces.getAsJsonObject(orientation.name().toLowerCase()),
orientation, variables);
}
}
}
private void applyTexture(JsonObject faceJson, FaceOrientation orientation, HashMap<String, String> variables) {
try {
uv.put(orientation, new InFaceUV(faceJson.getAsJsonArray("uv")));
} catch (Exception e) {
uv.put(orientation, new InFaceUV());
}
String textureName = getRealTextureName(faceJson.get("texture").getAsString(), variables);
Pair<Float, Float> texture = MainWindow.getRenderer().getTextureLoader().getTexture(textureName);
if (faceJson.has("cullface")) {
cullFaceTextures.put(orientation, texture);
} else {
textures.put(orientation, texture);
}
}
private String getRealTextureName(String textureName, HashMap<String, String> variables) {
if (textureName.contains("#")) {
if (variables.containsKey(textureName)) {
String newName = variables.get(textureName);
if (newName.contains("#")) {
if (newName.equals(textureName)) {
throw new IllegalArgumentException("self relation: " + textureName);
}
return getRealTextureName(newName, variables);
}
return newName;
} else {
throw new IllegalArgumentException("could not find variable " + textureName);
}
} else {
return textureName;
}
}
}

View File

@ -0,0 +1,32 @@
/*
* Codename 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.render.blockModels;
import com.google.gson.JsonArray;
public class SubBlockPosition {
int x, y, z;
public SubBlockPosition(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public SubBlockPosition(JsonArray json) {
x = json.get(0).getAsInt();
y = json.get(1).getAsInt();
z = json.get(2).getAsInt();
}
}

View File

@ -11,7 +11,7 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.render.face;
package de.bixilon.minosoft.render.fullFace;
public enum FaceOrientation {
EAST(0), WEST(1), UP(2), DOWN(3), SOUTH(4), NORTH(5);

View File

@ -11,19 +11,19 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.render.face;
package de.bixilon.minosoft.render.fullFace;
import de.bixilon.minosoft.game.datatypes.world.BlockPosition;
import javafx.util.Pair;
import org.apache.commons.collections.primitives.ArrayFloatList;
import static de.bixilon.minosoft.render.face.RenderConstants.UV;
import static de.bixilon.minosoft.render.fullFace.RenderConstants.UV;
public class FacePosition {
public class FullFacePosition {
private final BlockPosition blockPosition;
private final FaceOrientation faceOrientation;
public FacePosition(BlockPosition blockPosition, FaceOrientation faceOrientation) {
public FullFacePosition(BlockPosition blockPosition, FaceOrientation faceOrientation) {
this.blockPosition = blockPosition;
this.faceOrientation = faceOrientation;
}

View File

@ -0,0 +1,32 @@
/*
* Codename 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.render.fullFace;
import com.google.gson.JsonArray;
public class InFaceUV {
int u1, v1, u2, v2;
public InFaceUV(JsonArray json) {
u1 = json.get(0).getAsInt();
v1 = json.get(1).getAsInt();
u2 = json.get(2).getAsInt();
v2 = json.get(3).getAsInt();
}
public InFaceUV() {
u1 = v1 = 0;
u2 = v2 = 16;
}
}

View File

@ -11,7 +11,7 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.render.face;
package de.bixilon.minosoft.render.fullFace;
public class RenderConstants {
//TODO: fix rotated faces

View File

@ -11,7 +11,7 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.movement;
package de.bixilon.minosoft.render.movement;
import de.bixilon.minosoft.render.utility.Vec3;

View File

@ -11,7 +11,7 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.movement;
package de.bixilon.minosoft.render.movement;
import de.bixilon.minosoft.game.datatypes.world.BlockPosition;
import de.bixilon.minosoft.game.datatypes.world.World;

View File

@ -11,7 +11,7 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.movement;
package de.bixilon.minosoft.render.movement;
import de.bixilon.minosoft.game.datatypes.GameMode;
import de.bixilon.minosoft.game.datatypes.world.World;

View File

@ -15,7 +15,7 @@
* A simple camera controller to fly around the scene
*/
package de.bixilon.minosoft.movement;
package de.bixilon.minosoft.render.movement;
import de.bixilon.minosoft.render.MainWindow;
import de.bixilon.minosoft.render.utility.Vec3;

View File

@ -63,7 +63,7 @@ public class TextureLoader {
// this method has some bugs but it looks cool so let's just say it is an intended mechanic
Triplet<Float, Float, Float> rgbValues = getRGBTriplet(rgb);
float brightness = getBrightness(rgbValues);
rgbValues = multiply(new Triplet<>(94f / 255f, 157f / 255f, 52f / 255f), brightness);
rgbValues = multiply(new Triplet<>(94f / 255f, 157f / 255f, 52f / 255f), rgbValues.item1);
return getRGBInt(rgbValues);
}
@ -160,15 +160,18 @@ public class TextureLoader {
}
public Pair<Float, Float> getTexture(String name) {
// returns the start and end u-coordinatea of a specific texture to access it
String textureName = name;
if (textureName.contains("block/"))
textureName = textureName.substring(textureName.lastIndexOf('/') + 1);
// returns the start and end u-coordinate of a specific texture to access it
if (name == null) {
throw new NullPointerException("received null string as texture name");
}
if (name.contains("block/")) {
name = name.substring(name.lastIndexOf('/') + 1);
}
Integer pos = textureCoordinates.get(textureName);
Integer pos = textureCoordinates.get(name);
if (pos == null) {
// the texture does not exist
throw new IllegalArgumentException(String.format("could not find texture %s", textureName));
throw new IllegalArgumentException(String.format("could not find texture %s", name));
}
return new Pair<Float, Float>(

File diff suppressed because one or more lines are too long