Compare commits

..

57 Commits

Author SHA1 Message Date
James Seibel 42068fc152 Update the mod homepage 2022-02-11 20:30:44 -06:00
James Seibel 791d2c881a Update the version number for 1.6.0a 2022-02-11 20:17:34 -06:00
coolGi2007 9fff802baf Fixed shadow jar problem with toml in fabric 2022-02-11 13:35:20 +00:00
coolGi2007 d5c0f714fa Added _Version to config for future me 2022-02-11 13:07:24 +00:00
tom lee 09914af897 Hotfix Forge 1.17.1 non IDE IllegalAccessError 2022-02-11 19:29:36 +08:00
tom lee 7dd57345a4 Update core + Add missing MixinChunkGenerator back. (Which fix crashes) 2022-02-11 15:48:27 +08:00
James Seibel aff52ce926 Slightly improve the tooltips for the config GUI 2022-02-10 22:08:31 -06:00
tom lee 98ed33e2bf Update core + Config + fix blindness Fog 2022-02-10 22:16:30 +08:00
tom lee d4f4e7e24d Update core 2022-02-10 17:07:33 +08:00
tom lee cfc5f4cede Update core 2022-02-10 16:14:39 +08:00
tom lee e3611b00e1 Update core + Fixed the debug button not working 2022-02-10 14:54:34 +08:00
tom lee 8f6fb9cecc Update core 2022-02-10 11:40:11 +08:00
tom lee ba3f1fd0d0 Make chunk return true on isLightCorrect same as 1.16. 2022-02-10 11:12:40 +08:00
coolGi2007 932f3ca19a Made sodium use cursedforge and added toml to core 2022-02-10 13:10:01 +10:30
tom lee 7eb4339a1b Update everything up to latest state 2022-02-09 19:04:39 +08:00
James Seibel 21fd19d8d8 Add an expiration to the archives 2022-02-05 15:43:29 +00:00
coolGi2007 cfbca82905 Removed clouds 2022-02-05 09:46:52 +00:00
tom lee 11989b310e Middle-ported the Batch Generator 2022-02-05 16:08:18 +08:00
coolGi2007 c75f50a29a Cleaned up some gradle stuff 2022-01-30 16:02:20 +10:30
coolGi2007 3a0deb5111 Down-ported everything from 1.18 to 1.17 (not including world gen) 2022-01-28 19:46:02 +10:30
coolGi2007 c2462846db Downgraded stuff from 1.18 to 1.17 2022-01-26 05:06:37 +00:00
coolGi2007 66c183ba4f Added comments to the file 2022-01-25 05:09:31 +00:00
James Seibel 3966c668d9 Delete OptiFine_1.17.1_HD_U_H1.jar 2022-01-25 01:00:04 +00:00
coolGi2007 d1cc7740d3 Fixed accsesswideners 2022-01-24 23:41:22 +10:30
coolGi2007 9586cfe90d After all these years, the ints show up correctly after restarting (it was literally a 1 line fix) 2022-01-24 19:50:32 +10:30
coolGi2007 5a8194fc0d Updated everything from 1.18 to 1.17 2022-01-24 17:50:23 +10:30
coolGi2007 15a7678da2 Downgraded stuff from 1.18 to 1.17 2022-01-21 13:12:03 +10:30
cola98765 59f7a8571f resolved warnings 2022-01-18 14:21:58 +01:00
coolGi2007 e878954763 Added 1 jar thing 2022-01-18 10:09:34 +00:00
jas35484 a07282dd36 Add the missing minor version number 1.6a -> 1.6.0a 2022-01-17 20:35:50 -06:00
jas35484 df5923ea8e Increment the version from 'a1.5.4' to 'a1.6-pre' 2022-01-17 20:26:04 -06:00
jas35484 19350cc5d4 Add .gitlab-ci.yml 2022-01-17 19:51:19 -06:00
coolGi2007 1fd639a3f7 Escape button saves config 2022-01-14 14:05:44 +10:30
tom lee 69efd93ec3 Update core + Add DisableVanillaFog for Forge 2022-01-14 00:04:20 +08:00
tom lee c7575887ea Fixed Sodium Fog 2022-01-13 20:05:04 +08:00
tom lee 7902d483ec Update core. Port back fix for onChunkLoad light issue 2022-01-12 18:02:02 +08:00
coolGi2007 2bd74d379c Fixed immersive portals with cloud rendering 2022-01-12 16:31:36 +10:30
coolGi2007 1db8d3599b Fixes all (hopefully) problems with saving the config file 2022-01-11 17:37:20 +10:30
tom lee e80ccd38fe Fixed up SodiumAccessor 2022-01-10 22:05:31 +08:00
coolGi2007 12b7723017 Added cloud warning 2022-01-10 05:12:22 +00:00
coolGi2007 51341f14a3 Updated readme since fabric version was updated 2022-01-10 14:38:49 +10:30
coolGi2007 f07783deb1 Removed forge fog renderer to fix a crash 2022-01-10 14:18:07 +10:30
coolGi2007 c7e41973d3 Update accesswidener to fox something 2022-01-09 10:39:21 +00:00
coolGi2007 f90276d8a1 Fixed everything 2022-01-09 10:18:18 +00:00
tom lee 384fe016cd Updated common 2022-01-09 17:49:46 +08:00
coolGi2007 06301a42d6 oops 2022-01-09 09:45:59 +00:00
coolGi2007 b13626689b Updated everything(need to update the sodium stuff) 2022-01-09 20:09:06 +10:30
coolGi2007 ae820320de Updated everything 2022-01-07 07:15:29 +00:00
coolGi2007 4da96d094e Update Config.java 2022-01-02 08:58:50 +00:00
coolGi2007 d8196c2069 Removed the need for any config category. The config now guesses the category 2022-01-02 06:06:44 +00:00
coolGi2007 c5e0f35a63 Reordered the forge mixin 2022-01-02 05:15:35 +00:00
coolGi2007 8a76887386 Updated core and fixed config crash 2022-01-02 03:49:50 +00:00
coolGi2007 2d495b981f Updated core 2022-01-01 22:28:57 +10:30
coolGi2007 95b5d94596 Updated stuff 2021-12-31 21:35:13 +10:30
coolGi2007 b4de7cbd0b Fixed ConfigGui 2021-12-29 05:47:09 +00:00
coolGi2007 27b4cde1dc Fixed a broken thing 2021-12-28 11:40:41 +00:00
coolGi2007 ed2b28aa30 More universal config (works with java 8 & 16) 2021-12-28 10:46:13 +00:00
78 changed files with 2289 additions and 2076 deletions
+12 -21
View File
@@ -1,11 +1,4 @@
# THIS VERSION IS NO LONGER MAINTAINED! ALL DEVELOPMENT HAVE BEEN MOVED OVER TO THE MAIN BRANCH
# <img src="https://gitlab.com/jeseibel/distant-horizons-core/-/raw/main/_logo%20files/LOD%20logo%20flat%20-%20with%20boarder.png" width="32"> Distant Horizons
> A mod that adds a Level of Detail System to Minecraft
# What is Distant Horizons?
# Distant Horizons
This mod adds a Level Of Detail (LOD) system to Minecraft.\
This implementation renders simplified chunks outside the normal render distance\
@@ -17,15 +10,16 @@ If you want to see a quick demo, check out a video covering the mod here:
<a href="https://www.youtube.com/watch?v=H2tnvEVbO1c" target="_blank">![Minecraft Level Of Detail (LOD) mod - Alpha 1.5](https://i.ytimg.com/vi_webp/H2tnvEVbO1c/mqdefault.webp)</a>
Architectury version: 3.4-SNAPSHOT\
Forge version: 36.2.28\
Fabric version: 0.13.2\
Fabric API version: 0.42.0+1.16
Forge version: 37.1.0\
Fabric version: 0.12.6\
Fabric API version: 0.37.1+1.17
Modmenu version: 1.16.22
Modmenu version: 2.0.14\
Sodium version: mc1.17.1-0.3.3
Notes:\
This version has been confirmed to work in Eclipse and Retail Minecraft.\
(Retail running forge version 1.16.5-36.1.0 and fabric version 1.16.5-0.12.3)
(Retail running forge version 1.17.1-37.1.0 and fabric version 1.17.1-0.12.6)
## source code installation
@@ -54,15 +48,13 @@ Side note: invalidate caches and restart if required
**Using GUI**
1. Open a command line in the project folder
2. Run the command: `./gradlew build`
5. Then run command: `./gradlew mergeJars`
6. The compiled jar file will be in the folder `Merged`
3. The compiled jar file will be in the folder `fabric/build/libs/` and `forge/build/libs/`
**If in terminal:**
1. `git clone -b 1.16.5_architectury --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git`
1. `git clone -b 1.17.1 --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git`
2. `cd minecraft-lod-mod`
3. `./gradlew assemble`
5. `./gradlew mergeJars`
6. The compiled jar file will be in the folder `Merged`
3. `./gradlew assemble` or `./gradlew build`
4. The build should be in `fabric/build/libs/` and `forge/build/libs/`
## Other commands
@@ -83,8 +75,7 @@ Source code uses Mojang mappings.
Build only Fabric: `./gradlew fabric:assemble` or `./gradlew fabric:build`\
Build only Forge: `./gradlew fabric:assemble` or `./gradlew forge:build`\
Run the Fabric client (for debugging): `./gradlew fabric:runClient`\
Run the Forge client (**THIS DOST WORK** due to a bug with architectury): `./gradlew forge:runClient`\
To use a custom version of Java use `-D` then the path for Java
Run the Forge client (for debugging): `./gradlew forge:runClient`
## Open Source Acknowledgements
+2 -50
View File
@@ -8,7 +8,7 @@ buildscript {
plugins {
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "0.10.0-SNAPSHOT" apply false
id "dev.architectury.loom" version "0.10.0.195" apply false
}
apply plugin: JarMergerPlugin
@@ -50,14 +50,6 @@ subprojects { p ->
shadowMe(project(":core")) { transitive false }
}
}
jar {
manifest {
attributes 'Implementation-Title': rootProject.archives_base_name,
'Implementation-Version': rootProject.mod_version,
'Main-Class': 'com.seibel.lod.core.JarMain'
}
}
}
allprojects {
@@ -106,49 +98,9 @@ allprojects {
}
}
// Put stuff from gradle.properties into the mod info
processResources {
def resourceTargets = ["fabric.mod.json", "META-INF/mods.toml"] // Location of where to put
def intoTargets = ["$buildDir/resources/main/"] // Location of the built resources folder
def replaceProperties = [
version: mod_version,
mod_name: mod_name,
authors: mod_authors,
description: mod_description,
homepage: mod_homepage,
source: mod_source,
issues: mod_issues
] // The left side is what gets replaced in the mod info and the right side is where to get it from in the gradle.properties
inputs.properties replaceProperties
replaceProperties.put 'project', project
filesMatching(resourceTargets) {
expand replaceProperties
}
intoTargets.each { target ->
if (file(target).exists()) {
copy {
from(sourceSets.main.resources) {
include resourceTargets
expand replaceProperties
}
into target
}
}
}
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
// JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
// We'll use that if it's available, but otherwise we'll use the older option.
def targetVersion = 8
if (JavaVersion.current().isJava9Compatible()) {
options.release = targetVersion
}
options.release = 16
}
java {
@@ -27,8 +27,6 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IWorldGenerator;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IMultiplayer;
import net.minecraft.client.renderer.DimensionSpecialEffects;
/**
* This handles any configuration the user has access to.
@@ -74,9 +72,6 @@ public class Config extends ConfigGui
@ConfigAnnotations.ScreenEntry
public static WorldGenerator worldGenerator;
@ConfigAnnotations.ScreenEntry
public static Multiplayer multiplayer;
@ConfigAnnotations.ScreenEntry
public static Advanced advanced;
@@ -150,7 +145,7 @@ public class Config extends ConfigGui
public static boolean disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DEFAULT;
}
public static class AdvancedGraphics
{
@ConfigAnnotations.FileComment
@@ -185,16 +180,16 @@ public class Config extends ConfigGui
@ConfigAnnotations.Entry
public static boolean enableDistantGeneration = IWorldGenerator.ENABLE_DISTANT_GENERATION_DEFAULT;
// @ConfigAnnotations.FileComment
// @ConfigAnnotations.FileComment
// public static String _distanceGenerationMode = IWorldGenerator.getDistanceGenerationModeDesc();
@ConfigAnnotations.Entry
public static DistanceGenerationMode distanceGenerationMode = IWorldGenerator.DISTANCE_GENERATION_MODE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _lightGenerationMode = IWorldGenerator.LIGHT_GENERATION_MODE_DESC;
@ConfigAnnotations.Entry
public static LightGenerationMode lightGenerationMode = IWorldGenerator.LIGHT_GENERATION_MODE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _generationPriority = IWorldGenerator.GENERATION_PRIORITY_DESC;
@ConfigAnnotations.Entry
@@ -203,23 +198,17 @@ public class Config extends ConfigGui
/*
@ConfigAnnotations.FileComment
public static String _allowUnstableFeatureGeneration = IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DESC;
// FIXME: Temperary override. In 1.18, the newer Unstable gnerator is more usable
@ConfigAnnotations.Entry
public static boolean allowUnstableFeatureGeneration = IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT;
public static boolean allowUnstableFeatureGeneration = true;//IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT;
*/
@ConfigAnnotations.FileComment
public static String _blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DESC;
@ConfigAnnotations.Entry
public static BlocksToAvoid blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT;
}
public static class Multiplayer {
@ConfigAnnotations.FileComment
public static String _serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DESC;
@ConfigAnnotations.Entry
public static ServerFolderNameMode serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DEFAULT;
}
public static class Advanced
{
@ConfigAnnotations.ScreenEntry
@@ -274,7 +263,7 @@ public class Config extends ConfigGui
@ConfigAnnotations.FileComment
public static String _gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DESC;
@ConfigAnnotations.Entry(minValue = 0, maxValue = 50)
@ConfigAnnotations.Entry(minValue = 0, maxValue = 5000)
public static int gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DEFAULT.defaultValue;
@ConfigAnnotations.FileComment
@@ -4,7 +4,6 @@ import com.seibel.lod.common.forge.LodForgeMethodCaller;
import com.seibel.lod.common.networking.NetworkInterface;
import com.seibel.lod.common.wrappers.DependencySetup;
import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.core.ModInfo;
/**
* This is the common main class
@@ -1,7 +1,8 @@
package com.seibel.lod.common.forge;
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
@@ -15,5 +16,6 @@ import java.util.Random;
* @author Ran
*/
public interface LodForgeMethodCaller {
List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random);
List<BakedQuad> getQuads(MinecraftWrapper mc, Block block, BlockState blockState, Direction direction, Random random);
int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y);
}
@@ -1,11 +1,8 @@
package com.seibel.lod.common.networking;
import com.seibel.lod.common.LodCommonMain;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
import java.nio.charset.StandardCharsets;
/**
* This class holds most of the networking code for the mod.
* @author Ran
@@ -1,13 +1,15 @@
package com.seibel.lod.common.wrappers;
import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.common.wrappers.block.BlockColorSingletonWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.handlers.ReflectionHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
@@ -23,14 +25,13 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
*/
public class DependencySetup {
public static void createInitialBindings() {
SingletonHandler.bind(IVersionConstants.class, VersionConstants.INSTANCE);
SingletonHandler.bind(IBlockColorSingletonWrapper.class, BlockColorSingletonWrapper.INSTANCE);
if (!LodCommonMain.serverSided) {
SingletonHandler.bind(IMinecraftWrapper.class, MinecraftClientWrapper.INSTANCE);
SingletonHandler.bind(IMinecraftWrapper.class, MinecraftWrapper.INSTANCE);
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftClientWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftClientWrapper.INSTANCE.getOptions()));
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftWrapper.INSTANCE.getOptions()));
SingletonHandler.bind(IVersionConstants.class, VersionConstants.INSTANCE);
}
SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
DependencySetupDoneCheck.isDone = true;
}
}
@@ -1,7 +0,0 @@
package com.seibel.lod.common.wrappers;
public class DependencySetupDoneCheck
{
public static boolean isDone = false;
}
@@ -46,17 +46,9 @@ public class McObjectConverter
return matrix;
}
static final Direction[] directions;
static {
LodDirection[] lodDirs = LodDirection.values();
directions = new Direction[lodDirs.length];
for (LodDirection lodDir : lodDirs) {
directions[lodDir.ordinal()] = Direction.byName(lodDir.name());
}
}
public static Direction Convert(LodDirection lodDirection)
{
return directions[lodDirection.ordinal()];
return Direction.byName(lodDirection.name());
}
}
@@ -52,9 +52,4 @@ public class VersionConstants implements IVersionConstants {
public boolean hasBatchGenerationImplementation() {
return true;
}
@Override
public boolean isVanillaRenderedChunkSquare() {
return true;
}
}
@@ -83,8 +83,8 @@ public class WrapperFactory implements IWrapperFactory {
}
@Override
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder,
LodDimension newLodDimension, IWorldWrapper worldWrapper) {
return new BatchGenerationEnvironment(worldWrapper, newLodBuilder, newLodDimension);
}
}
@@ -0,0 +1,46 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* 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, version 3.
*
* 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/>.
*/
package com.seibel.lod.common.wrappers.block;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import net.minecraft.world.level.block.Blocks;
/**
* Contains methods that would have been static in BlockColorWrapper.
* Since interfaces can't create/implement static methods we have
* to split the object up in two.
*
* @author James Seibel
* @version 11-17-2021
*/
public class BlockColorSingletonWrapper implements IBlockColorSingletonWrapper
{
public static final BlockColorSingletonWrapper INSTANCE = new BlockColorSingletonWrapper();
@Override
public IBlockColorWrapper getWaterColor()
{
return BlockColorWrapper.getBlockColorWrapper(Blocks.WATER);
}
}
@@ -0,0 +1,328 @@
package com.seibel.lod.common.wrappers.block;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BushBlock;
import net.minecraft.world.level.block.FlowerBlock;
import net.minecraft.world.level.block.GrassBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.TallGrassBlock;
import net.minecraft.world.level.block.state.BlockState;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class BlockColorWrapper implements IBlockColorWrapper
{
//set of block which require tint
public static final ConcurrentMap<Block, BlockColorWrapper> blockColorWrapperMap = new ConcurrentHashMap<>();
// public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
public static final AbstractBlockPosWrapper blockPos = new BlockPosWrapper(0, 0, 0);
public static final Random random = new Random(0);
//public static BlockColourWrapper WATER_COLOR = getBlockColorWrapper(Blocks.WATER);
public static final Direction[] directions = new Direction[] { Direction.UP, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.DOWN };
private final Block block;
private int color;
private boolean isColored;
private boolean toTint;
private boolean foliageTint;
private boolean grassTint;
private boolean waterTint;
/**Constructor only require for the block instance we are wrapping**/
public BlockColorWrapper(Block block)
{
this.block = block;
this.color = 0;
this.isColored = true;
this.toTint = false;
this.foliageTint = false;
this.grassTint = false;
this.waterTint = false;
setupColorAndTint();
/*StringBuilder s = new StringBuilder();
s.append(block + "\n"
+ Integer.toHexString(
Minecraft.getInstance().getBlockColors().createDefault().getColor(
block.defaultBlockState(),
(World) MinecraftWrapper.INSTANCE.getWrappedServerLevel().getLevel(),
blockPosWrapper.getBlockPos())) + "\n"
);
for(Property x : Minecraft.getInstance().getBlockColors().getColoringProperties(block))
s.append(x.getName() + " " + x.getPossibleValues() + '\n');
System.out.println(s);*/
//System.out.println(block + " color " + Integer.toHexString(color) + " to tint " + toTint + " folliageTint " + folliageTint + " grassTint " + grassTint + " waterTint " + waterTint);
}
/**
* this return a wrapper of the block in input
* @param block object of the block to wrap
*/
public static IBlockColorWrapper getBlockColorWrapper(Block block)
{
//first we check if the block has already been wrapped
if (blockColorWrapperMap.containsKey(block) && blockColorWrapperMap.get(block) != null)
return blockColorWrapperMap.get(block);
//if it hasn't been created yet, we create it and save it in the map
BlockColorWrapper blockWrapper = new BlockColorWrapper(block);
blockColorWrapperMap.put(block, blockWrapper);
//we return the newly created wrapper
return blockWrapper;
}
/**
* Generate the color of the given block from its texture
* and store it for later use.
*/
private void setupColorAndTint()
{
BlockState blockState = block.defaultBlockState();
//BlockPosWrapper blockPosWrapper = new BlockPosWrapper();
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
TextureAtlasSprite texture;
List<BakedQuad> quads = null;
//boolean isTinted = false;
//int listSize = 0;
// first step is to check if this block has a tinted face
//for (Direction direction : directions)
//{
// quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random);
// listSize = Math.max(listSize, quads.size());
// for (BakedQuad bakedQuad : quads)
// {
// isTinted |= bakedQuad.isTinted();
// }
//}
//if it contains a tinted face then we store this block in the toTint set
//if (isTinted)
// this.toTint = true;
//now we get the first non-empty face
for (Direction direction : directions)
{
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random);
if (!quads.isEmpty())
break;
}
//the quads list is not empty we extract the first one
if (!quads.isEmpty())
{
isColored = true;
texture = quads.get(0).getSprite();
}
else
{
isColored = true;
texture = mc.getModelManager().getBlockModelShaper().getParticleIcon(block.defaultBlockState());
}
int count = 0;
int alpha = 0;
int red = 0;
int green = 0;
int blue = 0;
int numberOfGreyPixel = 0;
int tempColor;
int colorMultiplier;
// generate the block's color
// for (int frameIndex = 0; frameIndex < texture.getFrameCount(); frameIndex++)
boolean lookForTint = grassInstance() || leavesInstance() || waterIstance();
int frameIndex = 0; // TODO
{
// textures normally use u and v instead of x and y
for (int u = 0; u < texture.getWidth(); u++)
{
for (int v = 0; v < texture.getHeight(); v++)
{
//FIXME: Better way on the TextureAtlasSpriteWrapper!!!
tempColor = LodCommonMain.forge ?
LodCommonMain.forgeMethodCaller.getPixelRGBA(texture, frameIndex, u, v)
: TextureAtlasSpriteWrapper.getPixelRGBA(texture, frameIndex, u, v);
if (tempColor == 0)
continue;
if (lookForTint)
{
// determine if this pixel is gray
int colorMax = Math.max(Math.max(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
int colorMin = 4 + Math.min(Math.min(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
boolean isGray = colorMax < colorMin;
if (isGray)
numberOfGreyPixel++;
}
// for flowers, weight their non-green color higher
if (block instanceof FlowerBlock && (!(ColorUtil.getGreen(tempColor) > (ColorUtil.getBlue(tempColor) + 30)) || !(ColorUtil.getGreen(tempColor) > (ColorUtil.getRed(tempColor) + 30))))
colorMultiplier = 5;
else
colorMultiplier = 1;
// add to the running averages
count += colorMultiplier;
alpha += ColorUtil.getAlpha(tempColor) * colorMultiplier;
red += ColorUtil.getBlue(tempColor) * colorMultiplier;
green += ColorUtil.getGreen(tempColor) * colorMultiplier;
blue += ColorUtil.getRed(tempColor) * colorMultiplier;
}
}
}
if (count == 0)
// this block is entirely transparent
tempColor = 0;
else
{
// determine the average color
alpha /= count;
red /= count;
green /= count;
blue /= count;
tempColor = ColorUtil.rgbToInt(alpha, red, green, blue);
}
// determine if this block should use the biome color tint
if (lookForTint && (float) numberOfGreyPixel / count > 0.75f)
this.toTint = true;
// we check which kind of tint we need to apply
this.grassTint = grassInstance() && toTint;
this.foliageTint = leavesInstance() && toTint;
this.waterTint = waterIstance() && toTint;
//hardcoded leaves
if (block == Blocks.SPRUCE_LEAVES)
color = ColorUtil.multiplyRGBcolors(tempColor, 0xFF619961);
else if (block == Blocks.BIRCH_LEAVES)
color = ColorUtil.multiplyRGBcolors(tempColor, 0xFF80A755);
else
color = tempColor;
}
/** determine if the given block should use the biome's grass color */
private boolean grassInstance()
{
return block instanceof GrassBlock
|| block instanceof BushBlock
// || block instanceof IGrowable
// || block instanceof AbstractPlantBlock
// || block instanceof AbstractTopPlantBlock
|| block instanceof TallGrassBlock;
}
/** determine if the given block should use the biome's foliage color */
private boolean leavesInstance()
{
return (block instanceof LeavesBlock && block != Blocks.SPRUCE_LEAVES && block != Blocks.BIRCH_LEAVES/* && block != Blocks.AZALEA_LEAVES && block != Blocks.FLOWERING_AZALEA_LEAVES*/)
|| block == Blocks.VINE
|| block == Blocks.SUGAR_CANE;
}
/** determine if the given block should use the biome's foliage color */
private boolean waterIstance()
{
return block == Blocks.WATER;
}
@Override
public String getName(){
return block.getName().toString();
}
//--------------//
//Colors getters//
//--------------//
@Override
public boolean hasColor()
{
return isColored;
}
@Override
public int getColor()
{
return color;
}
//------------//
//Tint getters//
//------------//
@Override
public boolean hasTint()
{
return toTint;
}
@Override
public boolean hasGrassTint()
{
return grassTint;
}
@Override
public boolean hasFolliageTint()
{
return foliageTint;
}
@Override
public boolean hasWaterTint()
{
return waterTint;
}
@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof BlockColorWrapper))
return false;
BlockColorWrapper that = (BlockColorWrapper) o;
return Objects.equals(block, that.block);
}
@Override public int hashCode()
{
return Objects.hash(block);
}
}
@@ -1,286 +0,0 @@
package com.seibel.lod.common.wrappers.block;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.wrapperInterfaces.block.BlockDetail;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.FlowerBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.VoxelShape;
public class BlockDetailMap
{
public static final int FLOWER_COLOR_SCALE = 5;
public static final Random random = new Random(0);
//TODO: Perhaps make this not just use the first frame?
//FIXME: Stuff is wrong.
private static int calculateColorFromTexture(TextureAtlasSprite texture, boolean useFlowerScaling, boolean useFastLeaf) {
int count = 0;
double alpha = 0;
double red = 0;
double green = 0;
double blue = 0;
int tempColor;
{
// textures normally use u and v instead of x and y
for (int u = 0; u < texture.getWidth(); u++)
{
for (int v = 0; v < texture.getHeight(); v++)
{
//note: Minecraft color format is: 0xAA BB GG RR
//________ DH mod color format is: 0xAA RR GG BB
//OpenGL RGBA format native order: 0xRR GG BB AA
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
double r = ((tempColor & 0x000000FF) )/255.;
double g = ((tempColor & 0x0000FF00) >>> 8)/255.;
double b = ((tempColor & 0x00FF0000) >>> 16)/255.;
double a = ((tempColor & 0xFF000000) >>> 24)/255.;
int scale = 1;
if (useFastLeaf) {
r *= a;
g *= a;
b *= a;
a = 1.;
} else if (a==0.) {
continue;
} else if (useFlowerScaling && (g+0.1<b || g+0.1<r)) {
scale = FLOWER_COLOR_SCALE;
}
count += scale;
alpha += a*a*scale;
red += r*r*scale;
green += g*g*scale;
blue += b*b*scale;
}
}
}
if (count == 0)
// this block is entirely transparent
tempColor = ColorUtil.rgbToInt(255,255,0,255);
else
{
// determine the average color
tempColor = ColorUtil.rgbToInt(
(int) (Math.sqrt(alpha/count)*255.),
(int) (Math.sqrt(red / count)*255.),
(int) (Math.sqrt(green / count)*255.),
(int) (Math.sqrt(blue / count)*255.));
}
// TODO: Remove this when transparency is added!
double colorAlpha = ColorUtil.getAlpha(tempColor)/255.;
tempColor = ColorUtil.rgbToInt(
ColorUtil.getAlpha(tempColor),
(int)(ColorUtil.getRed(tempColor) * colorAlpha),
(int)(ColorUtil.getGreen(tempColor) * colorAlpha),
(int)(ColorUtil.getBlue(tempColor) * colorAlpha)
);
return tempColor;
}
static class BlockDetailCache {
static BlockDetailCache NULL_BLOCK_DETAIL = new BlockDetailCache();
private static final Block[] BLOCK_TO_AVOID = {Blocks.AIR, Blocks.CAVE_AIR, Blocks.BARRIER};
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
ConcurrentHashMap<Biome, BlockDetail> biomeDetailMap = null;
BlockDetail blockDetail;
BlockDetail defaultTintedDetail = null;
boolean requireResolving;
@SuppressWarnings("unused")
boolean requireShade; //TODO: Add back using this in renderer
@SuppressWarnings("unused")
boolean scaleFlowerColor; //FIXME: Do I need to scale the tint color???
int tintIndex;
static boolean isBlockToBeAvoid(Block b) {
for (Block bta : BLOCK_TO_AVOID)
if (bta==b) return true;
return false;
}
static boolean hasNoCollision(BlockState bs, BlockPos pos, LevelReader getter) {
if (!bs.getFluidState().isEmpty() || bs.getBlock() instanceof LiquidBlock) // Is blockState a fluid?
return false;
if (bs.getCollisionShape(getter, pos).isEmpty())
return true;
return false;
}
static boolean hasOnlyNonFullFace(BlockState bs, BlockPos pos, LevelReader getter) {
if (!bs.getFluidState().isEmpty() || bs.getBlock() instanceof LiquidBlock) // Is blockState a fluid?
return false;
VoxelShape voxelShape = bs.getShape(getter, pos);
if (voxelShape.isEmpty()) return true;
AABB bbox = voxelShape.bounds();
double xWidth = (bbox.maxX - bbox.minX);
double yWidth = (bbox.maxY - bbox.minY);
double zWidth = (bbox.maxZ - bbox.minZ);
return xWidth < 1 && zWidth < 1 && yWidth < 1;
}
static BlockDetailCache make(BlockState bs, BlockPos pos, LevelReader getter) {
boolean noCol, nonFull, canOcclude;
if(!bs.getFluidState().isEmpty()) {
bs = bs.getFluidState().createLegacyBlock();
FluidState fs = bs.getFluidState();
fs.getType();
noCol = false;
nonFull = false;
canOcclude = false;
BlockDetailCache result = new BlockDetailCache(fs);
//ApiShared.LOGGER.info(fs.toString()+" = ["+result+"]");
return result;
} else {
if (bs.getRenderShape() != RenderShape.MODEL) return NULL_BLOCK_DETAIL;
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
//BlocksToAvoid toAvoid = CONFIG.client().worldGenerator().getBlocksToAvoid();
noCol = hasNoCollision(bs, pos, getter);
nonFull = hasOnlyNonFullFace(bs, pos, getter);
canOcclude = bs.canOcclude();
List<BakedQuad> quads = null;
for (Direction direction : DIRECTION_ORDER)
{
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(bs).getQuads(bs, direction, random);
if (!quads.isEmpty() && !(bs.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP))
break;
};
if (quads == null || quads.isEmpty()) return NULL_BLOCK_DETAIL;
BlockDetailCache result = new BlockDetailCache(canOcclude, noCol, nonFull, quads.get(0),
bs.getBlock() instanceof FlowerBlock, bs.getBlock() instanceof LeavesBlock);
// ApiShared.LOGGER.info(bs.toString()+" = ["+result+"]");
return result;
}
}
BlockDetailCache(boolean isFullBlock, boolean noCol, boolean nonFull, BakedQuad quad, boolean useFlowerScaling, boolean useFastLeaf) {
requireResolving = quad.isTinted();
requireShade = quad.isShade();
tintIndex = quad.getTintIndex();
scaleFlowerColor = useFlowerScaling;
blockDetail = new BlockDetail(calculateColorFromTexture(quad.sprite, useFlowerScaling, useFastLeaf), isFullBlock, noCol, nonFull);
if (quad.isTinted()) biomeDetailMap = new ConcurrentHashMap<Biome, BlockDetail>();
}
BlockDetailCache(FluidState fluid) {
requireResolving = true; // TODO: Maybe in the future recheck that there really is no way to see if a fluid needs tinting
requireShade = false;
tintIndex = 0; // Vanilla doesn't use this index currently. (Checked at 1.18.X, See BlockColors.class)
scaleFlowerColor = false;
TextureAtlasSprite text = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(fluid.createLegacyBlock()).getParticleIcon();
blockDetail = new BlockDetail(calculateColorFromTexture(text, false, false), true, false, false);
biomeDetailMap = new ConcurrentHashMap<Biome, BlockDetail>();
}
private BlockDetailCache()
{
//DUMMY CREATOR
}
BlockDetail getResolvedBlockDetail(BlockState bs, int x, int y, int z, LevelReader getter) {
if (!requireResolving) return blockDetail;
BlockPos pos = new BlockPos(x,y,z);
Biome biome = getter.getBiome(pos);
BlockDetail tintDetail = biomeDetailMap.get(biome);
if (tintDetail == null) {
if (!bs.getFluidState().isEmpty()) bs = bs.getFluidState().createLegacyBlock();
BlockColors bc = Minecraft.getInstance().getBlockColors();
int tintColor = bc.getColor(bs, getter, pos, tintIndex);
tintColor = ColorUtil.multiplyARGBwithRGB(blockDetail.color, tintColor);
tintDetail = new BlockDetail(tintColor, blockDetail.isFullBlock,
blockDetail.hasNoCollision, blockDetail.hasOnlyNonFullFace);
BlockDetail tintDetailCAS = biomeDetailMap.putIfAbsent(biome, tintDetail);
if (tintDetailCAS != null) tintDetail = tintDetailCAS;
}
return tintDetail;
}
// Note: this one won't resolve biome based or pos based colors. (Kinda like GUI block icons)
BlockDetail getResolvedBlockDetail(BlockState bs) {
if (!requireResolving) return blockDetail;
if (defaultTintedDetail != null) return defaultTintedDetail;
BlockColors bc = Minecraft.getInstance().getBlockColors();
if (!bs.getFluidState().isEmpty()) bs = bs.getFluidState().createLegacyBlock();
int tintColor = bc.getColor(bs, null, null, tintIndex);
if (tintColor == -1) {
defaultTintedDetail = blockDetail;
}
else {
defaultTintedDetail = new BlockDetail(ColorUtil.multiplyARGBwithRGB(blockDetail.color, tintColor),
blockDetail.isFullBlock, blockDetail.hasNoCollision, blockDetail.hasOnlyNonFullFace);
}
return defaultTintedDetail;
}
@Override
public String toString() {
return "[BlockDetail: "+blockDetail+", RequireResolving: "+requireResolving+", requireShade: "+requireShade+", scaleFlowerColor: "+scaleFlowerColor+"]";
}
}
private static ConcurrentHashMap<BlockState, BlockDetailCache> map = new ConcurrentHashMap<BlockState, BlockDetailCache>();
private BlockDetailMap() {}
private static BlockDetailCache getOrMakeBlockDetailCache(BlockState bs, BlockPos pos, LevelReader getter) {
BlockDetailCache cache = map.get(bs);
if (cache != null) return cache;
if (bs.getFluidState().isEmpty()) {
cache = BlockDetailCache.make(bs, pos, getter);
} else {
cache = BlockDetailCache.make(bs.getFluidState().createLegacyBlock(), pos, getter);
}
BlockDetailCache cacheCAS = map.putIfAbsent(bs, cache);
return cacheCAS==null ? cache : cacheCAS;
}
// Return null means skip the block
public static BlockDetail getBlockDetail(BlockState bs) {
BlockDetailCache cache = getOrMakeBlockDetailCache(bs, new BlockPos(0, 0, 0), null);
if (cache == BlockDetailCache.NULL_BLOCK_DETAIL) return null;
return cache.getResolvedBlockDetail(bs);
}
// Return null means skip the block
public static BlockDetail getBlockDetailWithCompleteTint(BlockState bs, int x, int y, int z, LevelReader tintGetter) {
BlockDetailCache cache = getOrMakeBlockDetailCache(bs, new BlockPos(x,y,z), tintGetter);
if (cache == BlockDetailCache.NULL_BLOCK_DETAIL) return null;
return cache.getResolvedBlockDetail(bs, x, y, z, tintGetter);
}
}
@@ -0,0 +1,158 @@
package com.seibel.lod.common.wrappers.block;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.VoxelShape;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class BlockShapeWrapper implements IBlockShapeWrapper
{
//set of block which require tint
public static final ConcurrentMap<Block, BlockShapeWrapper> blockShapeWrapperMap = new ConcurrentHashMap<>();
public static BlockShapeWrapper WATER_SHAPE = new BlockShapeWrapper();
private final Block block;
private final boolean toAvoid;
private boolean nonFull;
private boolean noCollision;
/**Constructor only require for the block instance we are wrapping**/
public BlockShapeWrapper(Block block, IChunkWrapper chunkWrapper, int x, int y, int z)
{
this.block = block;
this.nonFull = false;
this.noCollision = false;
this.toAvoid = ofBlockToAvoid();
setupShapes(chunkWrapper, x, y, z);
//System.out.println(block + " non full " + nonFull + " no collision " + noCollision + " to avoid " + toAvoid);
}
private BlockShapeWrapper()
{
this.block = Blocks.WATER;
this.nonFull = false;
this.noCollision = false;
this.toAvoid = false;
}
/**
* this return a wrapper of the block in input
* @param block Block object to wrap
*/
static public BlockShapeWrapper getBlockShapeWrapper(Block block, ChunkWrapper chunkWrapper, int x, int y, int z)
{
//first we check if the block has already been wrapped
if (blockShapeWrapperMap.containsKey(block) && blockShapeWrapperMap.get(block) != null)
return blockShapeWrapperMap.get(block);
//if it hasn't been created yet, we create it and save it in the map
BlockShapeWrapper blockWrapper = new BlockShapeWrapper(block, chunkWrapper, x, y, z);
blockShapeWrapperMap.put(block, blockWrapper);
//we return the newly created wrapper
return blockWrapper;
}
private void setupShapes(IChunkWrapper chunkWrapper, int x, int y, int z)
{
ChunkAccess chunk = ((ChunkWrapper) chunkWrapper).getChunk();
BlockPos blockPos = new BlockPos(x, y, z);
boolean noCollisionSetted = false;
boolean nonFullSetted = false;
if (!block.defaultBlockState().getFluidState().isEmpty())// || block instanceof SixWayBlock)
{
noCollisionSetted = true;
nonFullSetted = true;
noCollision = false;
nonFull = false;
}
if (!nonFullSetted)
{
VoxelShape voxelShape = block.defaultBlockState().getShape(chunk, blockPos);
if (!voxelShape.isEmpty())
{
AABB bbox = voxelShape.bounds();
double xWidth = (bbox.maxX - bbox.minX);
double yWidth = (bbox.maxY - bbox.minY);
double zWidth = (bbox.maxZ - bbox.minZ);
nonFull = xWidth < 1 && zWidth < 1 && yWidth < 1;
}
else
{
nonFull = false;
}
}
if (!noCollisionSetted)
{
VoxelShape collisionShape = block.defaultBlockState().getCollisionShape(chunk, blockPos);
noCollision = collisionShape.isEmpty();
}
}
@Override
public boolean ofBlockToAvoid()
{
return block.equals(Blocks.AIR)
|| block.equals(Blocks.CAVE_AIR)
|| block.equals(Blocks.BARRIER);
}
//-----------------//
//Avoidance getters//
//-----------------//
@Override
public boolean isNonFull()
{
return nonFull;
}
@Override
public boolean hasNoCollision()
{
return noCollision;
}
@Override
public boolean isToAvoid()
{
return toAvoid;
}
@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof BlockShapeWrapper))
return false;
BlockShapeWrapper that = (BlockShapeWrapper) o;
return Objects.equals(block, that.block);
}
@Override public int hashCode()
{
return Objects.hash(block);
}
}
@@ -18,7 +18,11 @@ public class TextureAtlasSpriteWrapper {
* The code has been modified to use TextureAtlasSprite
*/
public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) {
// Require access widener
return sprite.mainImage[0].getPixelRGBA(x + sprite.framesX[frameIndex] * sprite.getWidth(), y + sprite.framesY[frameIndex] * sprite.getHeight());
if (sprite.animatedTexture != null) {
x += sprite.animatedTexture.getFrameX(frameIndex) * sprite.width;
y += sprite.animatedTexture.getFrameY(frameIndex) * sprite.height;
}
return sprite.mainImage[0].getPixelRGBA(x, y);
}
}
@@ -44,12 +44,13 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
{
this.chunkPos = new ChunkPos(chunkX, chunkZ);
}
public ChunkPosWrapper(long l)
{
this.chunkPos = new ChunkPos(l);
}
public ChunkPosWrapper(ChunkPos pos)
{
this.chunkPos = pos;
@@ -85,13 +86,13 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
@Override
public int getRegionX()
{
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, LodUtil.REGION_DETAIL_LEVEL);
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, LodUtil.REGION_DETAIL_LEVEL);
}
@Override
public int getRegionZ()
{
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.z, LodUtil.REGION_DETAIL_LEVEL);
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.z, LodUtil.REGION_DETAIL_LEVEL);
}
public ChunkPos getChunkPos()
@@ -129,7 +130,7 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
public AbstractBlockPosWrapper getWorldPosition()
{
// the parameter here is the y position
BlockPos blockPos = chunkPos.getWorldPosition();
BlockPos blockPos = chunkPos.getMiddleBlockPosition(0);
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
}
@@ -1,26 +1,28 @@
package com.seibel.lod.common.wrappers.chunk;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
import com.seibel.lod.core.util.LevelPosUtil;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.block.BlockDetail;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.common.wrappers.WrapperUtil;
import com.seibel.lod.common.wrappers.block.BlockDetailMap;
import com.seibel.lod.common.wrappers.block.BlockColorWrapper;
import com.seibel.lod.common.wrappers.block.BlockShapeWrapper;
import com.seibel.lod.common.wrappers.world.BiomeWrapper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.QuartPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.LiquidBlockContainer;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.levelgen.Heightmap;
/**
@@ -31,17 +33,17 @@ import net.minecraft.world.level.levelgen.Heightmap;
public class ChunkWrapper implements IChunkWrapper
{
private ChunkAccess chunk;
private LevelReader lightSource;
private BlockAndTintGetter lightSource;
@Override
public int getHeight(){
return 255;
return chunk.getHeight();
}
@Override
public int getMinBuildHeight()
{
return 0;
return chunk.getMinBuildHeight();
}
@Override
public int getMaxBuildHeight()
@@ -59,13 +61,23 @@ public class ChunkWrapper implements IChunkWrapper
public IBiomeWrapper getBiome(int x, int y, int z)
{
return BiomeWrapper.getBiomeWrapper(chunk.getBiomes().getNoiseBiome(
x >> 2, y >> 2, z >> 2));
QuartPos.fromBlock(x), QuartPos.fromBlock(y), QuartPos.fromBlock(z)));
}
@Override
public BlockDetail getBlockDetail(int x, int y, int z) {
BlockState blockState = chunk.getBlockState(new BlockPos(x, y, z));
return BlockDetailMap.getBlockDetailWithCompleteTint(blockState, x, y, z, lightSource);
public IBlockColorWrapper getBlockColorWrapper(int x, int y, int z)
{
BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
Block block = blockState.getBlock();
return BlockColorWrapper.getBlockColorWrapper(block);
}
@Override
public IBlockShapeWrapper getBlockShapeWrapper(int x, int y, int z)
{
BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
Block block = blockState.getBlock();
return BlockShapeWrapper.getBlockShapeWrapper(block, this, x, y, z);
}
@Deprecated
@@ -74,7 +86,8 @@ public class ChunkWrapper implements IChunkWrapper
this.chunk = chunk;
this.lightSource = null;
}
public ChunkWrapper(ChunkAccess chunk, LevelReader lightSource) {
public ChunkWrapper(ChunkAccess chunk, BlockAndTintGetter lightSource)
{
this.chunk = chunk;
this.lightSource = lightSource;
}
@@ -95,12 +108,12 @@ public class ChunkWrapper implements IChunkWrapper
@Override
public int getRegionPosX(){
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, getChunkPosX(), LodUtil.REGION_DETAIL_LEVEL);
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, getChunkPosX(), LodUtil.REGION_DETAIL_LEVEL);
}
@Override
public int getRegionPosZ(){
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, getChunkPosZ(), LodUtil.REGION_DETAIL_LEVEL);
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, getChunkPosZ(), LodUtil.REGION_DETAIL_LEVEL);
}
@Override
@@ -125,9 +138,15 @@ public class ChunkWrapper implements IChunkWrapper
return chunk.getPos().getMinBlockZ();
}
@Override
public long getLongChunkPos() {
return chunk.getPos().toLong();
}
@Override
public boolean isLightCorrect(){
return true;//chunk.isLightCorrect();
return true;
//return chunk.isLightCorrect();
}
public boolean isWaterLogged(int x, int y, int z)
@@ -156,22 +175,4 @@ public class ChunkWrapper implements IChunkWrapper
if (lightSource == null) return -1;
return lightSource.getBrightness(LightLayer.SKY, new BlockPos(x, y, z));
}
@Override
public long getLongChunkPos() {
return chunk.getPos().toLong();
}
@Override
public boolean doesNearbyChunksExist() {
if (lightSource instanceof LightedWorldGenRegion) return true;
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (dx == 0 && dz == 0) continue;
if (lightSource.getChunk(dx + getChunkPosX(), dz + getChunkPosZ(), ChunkStatus.BIOMES, false) == null)
return false;
}
}
return true;
}
}
File diff suppressed because it is too large Load Diff
@@ -3,7 +3,6 @@ package com.seibel.lod.common.wrappers.config;
import com.seibel.lod.core.enums.config.*;
import com.seibel.lod.core.enums.rendering.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IMultiplayer;
import com.seibel.lod.common.Config;
/**
@@ -29,7 +28,6 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
{
public final IGraphics graphics;
public final IWorldGenerator worldGenerator;
public final IMultiplayer multiplayer;
public final IAdvanced advanced;
@@ -45,11 +43,6 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
return worldGenerator;
}
@Override
public IMultiplayer multiplayer() {
return multiplayer;
}
@Override
public IAdvanced advanced()
{
@@ -77,7 +70,6 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
{
graphics = new Graphics();
worldGenerator = new WorldGenerator();
multiplayer = new Multiplayer();
advanced = new Advanced();
}
@@ -185,7 +177,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.getEntry("client.graphics.quality.horizontalQuality").value = newHorizontalQuality;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.horizontalQuality");
}
@Override
public DropoffQuality getDropoffQuality() {
return Config.Client.Graphics.Quality.dropoffQuality;
@@ -269,7 +261,6 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.disableDirectionalCulling");
}
@Override
public VanillaOverdraw getVanillaOverdraw()
{
@@ -293,7 +284,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.backsideCullingRange").value = newBacksideCullingRange;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.backsideCullingRange");
}*/
@Override
public boolean getUseExtendedNearClipPlane()
{
@@ -341,6 +332,20 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.saveOption("client.worldGenerator.distanceGenerationMode");
}
/*
@Override
public boolean getAllowUnstableFeatureGeneration()
{
return Config.Client.WorldGenerator.allowUnstableFeatureGeneration;
}
@Override
public void setAllowUnstableFeatureGeneration(boolean newAllowUnstableFeatureGeneration)
{
ConfigGui.editSingleOption.getEntry("client.worldGenerator.allowUnstableFeatureGeneration").value = newAllowUnstableFeatureGeneration;
ConfigGui.editSingleOption.saveOption("client.worldGenerator.allowUnstableFeatureGeneration");
}*/
@Override
public BlocksToAvoid getBlocksToAvoid()
{
@@ -355,7 +360,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override
public boolean getEnableDistantGeneration()
{
return (boolean) ConfigGui.editSingleOption.getEntry("client.worldGenerator.enableDistantGeneration").value;
return Config.Client.WorldGenerator.enableDistantGeneration;
}
@Override
public void setEnableDistantGeneration(boolean newEnableDistantGeneration)
@@ -378,27 +383,6 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
//=====================//
// Multiplayer Configs //
//=====================//
public static class Multiplayer implements IMultiplayer
{
@Override
public ServerFolderNameMode getServerFolderNameMode()
{
return Config.Client.Multiplayer.serverFolderNameMode;
}
@Override
public void setServerFolderNameMode(ServerFolderNameMode newServerFolderNameMode)
{
ConfigGui.editSingleOption.getEntry("client.multiplayer.serverFolderNameMode").value = newServerFolderNameMode;
ConfigGui.editSingleOption.saveOption("client.multiplayer.serverFolderNameMode");
}
}
//============================//
// AdvancedModOptions Configs //
@@ -2,9 +2,8 @@ package com.seibel.lod.common.wrappers.config;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.ImageButton;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
@@ -12,9 +11,9 @@ import net.minecraft.resources.ResourceLocation;
* Creates a button with a texture on it
*/
public class TexturedButtonWidget extends ImageButton {
// public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, ResourceLocation texture, OnPress pressAction) {
// super(x, y, width, height, u, v, texture, pressAction);
// }
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, ResourceLocation texture, OnPress pressAction) {
super(x, y, width, height, u, v, texture, pressAction);
}
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction) {
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction);
}
@@ -27,20 +26,18 @@ public class TexturedButtonWidget extends ImageButton {
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, tooltipSupplier, text);
}
@Override
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta) {
@Override
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, WIDGETS_LOCATION);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha);
int i = this.getYImage(this.isHovered);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest();
this.blit(matrices, this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height);
this.blit(matrices, this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height);
Minecraft.getInstance().getTextureManager().bind(WIDGETS_LOCATION);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha);
int i = getYImage(isHovered());
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest();
this.blit(matrices, this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height);
this.blit(matrices, this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2,
this.height);
super.renderButton(matrices, mouseX, mouseY, delta);
}
super.renderButton(matrices, mouseX, mouseY, delta);
}
}
@@ -5,21 +5,17 @@ import java.util.HashSet;
import java.util.stream.Collectors;
import com.mojang.blaze3d.platform.NativeImage;
import com.seibel.lod.common.wrappers.WrapperFactory;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.lod.common.wrappers.misc.LightMapWrapper;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.api.ModAccessorApi;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import it.unimi.dsi.fastutil.objects.ObjectList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.world.phys.AABB;
import org.lwjgl.opengl.GL15;
import com.mojang.math.Vector3f;
import com.seibel.lod.core.objects.math.Mat4f;
@@ -28,20 +24,22 @@ import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.common.wrappers.WrapperFactory;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.FogType;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
@@ -50,7 +48,7 @@ import net.minecraft.world.phys.Vec3;
* related to rendering in Minecraft.
*
* @author James Seibel
* @version 12-14-2021
* @version 12-12-2021
*/
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
{
@@ -60,8 +58,6 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
private static final GameRenderer GAME_RENDERER = MC.gameRenderer;
private static final WrapperFactory FACTORY = WrapperFactory.INSTANCE;
@Override
public Vec3f getLookAtVector()
{
@@ -96,7 +92,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override
public Mat4f getDefaultProjectionMatrix(float partialTicks)
{
return McObjectConverter.Convert(GAME_RENDERER.getProjectionMatrix(GAME_RENDERER.getMainCamera(), partialTicks, true));
return McObjectConverter.Convert(GAME_RENDERER.getProjectionMatrix(GAME_RENDERER.getFov(GAME_RENDERER.getMainCamera(), partialTicks, true)));
}
@Override
@@ -106,9 +102,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
}
@Override
public Color getFogColor(float partialTick) {
float[] colorValues = new float[4];
GL15.glGetFloatv(GL15.GL_FOG_COLOR, colorValues);
public Color getFogColor(float partialTicks) {
FogRenderer.setupColor(GAME_RENDERER.getMainCamera(), partialTicks, MC.level, 1, GAME_RENDERER.getDarkenWorldAmount(partialTicks));
float[] colorValues = RenderSystem.getShaderFogColor();
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
}
// getSpecialFogColor() is the same as getFogColor()
@@ -151,46 +147,61 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
* is going to render this frame. <br><br>
* <p>
*/
public boolean usingBackupGetVanillaRenderedChunks = false;
@Override
public HashSet<AbstractChunkPosWrapper> getVanillaRenderedChunks()
{
ISodiumAccessor sodium = ModAccessorHandler.get(ISodiumAccessor.class);
ISodiumAccessor sodium = ModAccessorApi.get(ISodiumAccessor.class);
if (sodium != null)
{
return sodium.getNormalRenderedChunks();
}
IOptifineAccessor optifine = ModAccessorHandler.get(IOptifineAccessor.class);
IOptifineAccessor optifine = ModAccessorApi.get(IOptifineAccessor.class);
if (optifine != null)
{
HashSet<AbstractChunkPosWrapper> pos = optifine.getNormalRenderedChunks();
if (pos==null) pos = getMaximumRenderedChunks();
if (pos==null)
pos = getMaximumRenderedChunks();
return pos;
}
if (!usingBackupGetVanillaRenderedChunks) {
try {
LevelRenderer levelRenderer = MC.levelRenderer;
ObjectList<LevelRenderer.RenderChunkInfo> chunks = levelRenderer.renderChunks;
return (chunks.stream().map((chunk) -> {
AABB chunkBoundingBox = chunk.chunk.bb;
return FACTORY.createChunkPos(Math.floorDiv((int) chunkBoundingBox.minX, 16),
Math.floorDiv((int) chunkBoundingBox.minZ, 16));
}).collect(Collectors.toCollection(HashSet::new)));
} catch (LinkageError e) {
try {
MinecraftClientWrapper.INSTANCE.sendChatMessage(
"\u00A7e\u00A7l\u00A7uWARNING: Distant Horizons: getVanillaRenderedChunks method failed."
+ " Using Backup Method.");
MinecraftClientWrapper.INSTANCE.sendChatMessage(
"\u00A7eOverdraw prevention will be worse than normal.");
} catch (Exception e2) {}
ApiShared.LOGGER.error("getVanillaRenderedChunks Error: {}", e);
usingBackupGetVanillaRenderedChunks = true;
}
}
return getMaximumRenderedChunks();
LevelRenderer levelRenderer = MC.levelRenderer;
ObjectArrayList<LevelRenderer.RenderChunkInfo> chunks = levelRenderer.renderChunks;
return (chunks.stream().map((chunk) -> {
AABB chunkBoundingBox = chunk.chunk.bb;
return FACTORY.createChunkPos(Math.floorDiv((int) chunkBoundingBox.minX, 16),
Math.floorDiv((int) chunkBoundingBox.minZ, 16));
}).collect(Collectors.toCollection(HashSet::new)));
}
@Override
public HashSet<AbstractChunkPosWrapper> getMaximumRenderedChunks()
{
//TODO: Make this a circle
IMinecraftWrapper mcWrapper = SingletonHandler.get(IMinecraftWrapper.class);
IWrapperFactory factory = SingletonHandler.get(IWrapperFactory.class);
int chunkRenderDist = this.getRenderDistance();
AbstractChunkPosWrapper centerChunkPos = mcWrapper.getPlayerChunkPos();
int startChunkX = centerChunkPos.getX() - chunkRenderDist;
int startChunkZ = centerChunkPos.getZ() - chunkRenderDist;
// add every position within render distance
HashSet<AbstractChunkPosWrapper> renderedPos = new HashSet<AbstractChunkPosWrapper>();
for (int chunkX = 0; chunkX < (chunkRenderDist * 2+1); chunkX++)
{
for(int chunkZ = 0; chunkZ < (chunkRenderDist * 2+1); chunkZ++)
{
renderedPos.add(factory.createChunkPos(startChunkX + chunkX, startChunkZ + chunkZ));
}
}
return renderedPos;
}
@Override
public int[] getLightmapPixels()
{
@@ -203,12 +214,12 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
int lightMapHeight = getLightmapTextureHeight();
int lightMapWidth = getLightmapTextureWidth();
int pixels[] = new int[lightMapWidth * lightMapHeight];
int[] pixels = new int[lightMapWidth * lightMapHeight];
for (int u = 0; u < lightMapWidth; u++)
{
for (int v = 0; v < lightMapWidth; v++)
{
// this could probably be kept as a int, but
// this could probably be kept as an int, but
// it is easier to test and see the colors when debugging this way.
// When creating a new release this should be changed to the int version.
Color c = LodUtil.intToColor(lightMap.getLightValue(u, v));
@@ -224,11 +235,10 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
int col =
((c.getRed() & 0xFF) << 16) | // blue
((c.getGreen() & 0xFF) << 8) | // green
((c.getBlue() & 0xFF)) | // red
((c.getAlpha() & 0xFF) << 24); // alpha
((c.getGreen() & 0xFF) << 8) | // green
((c.getBlue() & 0xFF)) | // red
((c.getAlpha() & 0xFF) << 24); // alpha
// 2D array stored in a 1D array.
// Thank you Tim from College ;)
pixels[u * lightMapWidth + v] = col;
@@ -293,18 +303,13 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override
public boolean isFogStateSpecial() {
Camera camera = GAME_RENDERER.getMainCamera();
FogType fogType = camera.getFluidInCamera();
Entity entity = camera.getEntity();
boolean enableFog = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
enableFog |= fogType.equals(FogType.WATER);
enableFog |= fogType.equals(FogType.LAVA);
enableFog |= fogType.equals(FogType.POWDER_SNOW);
return enableFog;
Entity entity = GAME_RENDERER.getMainCamera().getEntity();
boolean isBlind = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
return GAME_RENDERER.getMainCamera().getFluidInCamera() != FogType.NONE || isBlind;
}
@Override
@Override
public boolean tryDisableVanillaFog() {
return true; // Handled via the MixinFogRenderer at fabric and forge
return true; // Handled via MixinFogRenderer in both Fabric and Forge
}
}
@@ -26,11 +26,10 @@ import java.util.ArrayList;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.platform.Window;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
@@ -70,9 +69,9 @@ import org.jetbrains.annotations.Nullable;
* @author James Seibel
* @version 9-16-2021
*/
public class MinecraftClientWrapper implements IMinecraftClientWrapper
public class MinecraftWrapper implements IMinecraftWrapper
{
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
public static final MinecraftWrapper INSTANCE = new MinecraftWrapper();
public final Minecraft mc = Minecraft.getInstance();
@@ -85,7 +84,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper
private ProfilerWrapper profilerWrapper;
private MinecraftClientWrapper()
private MinecraftWrapper()
{
}
@@ -241,7 +240,8 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper
@Override
public ChunkPosWrapper getPlayerChunkPos()
{
return new ChunkPosWrapper(getPlayer().chunkPosition().x, getPlayer().chunkPosition().z);
ChunkPos playerPos = getPlayer().chunkPosition();
return new ChunkPosWrapper(playerPos.x, playerPos.z);
}
public Options getOptions()
@@ -418,7 +418,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper
@Override
public void crashMinecraft(String errorMessage, Throwable exception)
{
ApiShared.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
ClientApi.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
CrashReport report = new CrashReport(errorMessage, exception);
Minecraft.crash(report);
}
@@ -23,13 +23,11 @@ import java.io.File;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.core.enums.WorldType;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
@@ -39,6 +37,7 @@ import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import org.jetbrains.annotations.Nullable;
/**
@@ -129,12 +128,24 @@ public class WorldWrapper implements IWorldWrapper
return world.dimensionType().hasSkyLight();
}
@Override
public boolean isEmpty()
{
return world == null;
}
@Override
public int getHeight()
{
return world.getHeight();
}
@Override
public short getMinHeight()
{
return (short) world.getMinBuildHeight();
}
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
@Override
public File getSaveFolder() throws UnsupportedOperationException
@@ -164,9 +175,11 @@ public class WorldWrapper implements IWorldWrapper
}
@Override
public ChunkWrapper tryGetChunk(AbstractChunkPosWrapper pos) {
public IChunkWrapper tryGetChunk(AbstractChunkPosWrapper pos) {
ChunkAccess chunk = world.getChunk(pos.getX(), pos.getZ(), ChunkStatus.EMPTY, false);
if (chunk == null) return null;
return new ChunkWrapper(chunk, world);
}
}
@@ -19,24 +19,23 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.enums.config.LightGenerationMode;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.util.GridList;
import com.seibel.lod.core.util.LodThreadFactory;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
import java.io.IOException;
import java.time.Duration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -58,14 +57,10 @@ import com.seibel.lod.common.wrappers.worldGeneration.step.StepSurface;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.levelgen.DebugLevelSource;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.lighting.LevelLightEngine;
@@ -83,14 +78,15 @@ Feature Step: 0.389072425s
Lod Generation: 0.269023348s
*/
public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnvionmentWrapper {
public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnvionmentWrapper
{
public static final boolean ENABLE_PERF_LOGGING = false;
public static final boolean ENABLE_EVENT_LOGGING = false;
public static final boolean ENABLE_LOAD_EVENT_LOGGING = false;
public static final boolean DISABLE_LOADING_SAVES = false;
// TODO: Make actual proper support for StarLight
public static class PrefEvent {
//TODO: Make actual proper support for StarLight
public static class PrefEvent
{
long beginNano = 0;
long emptyNano = 0;
long structStartNano = 0;
@@ -102,20 +98,27 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
long featureNano = 0;
long lightNano = 0;
long endNano = 0;
@Override
public String toString() {
return "beginNano: " + beginNano + ",\n" + "emptyNano: " + emptyNano + ",\n" + "structStartNano: "
+ structStartNano + ",\n" + "structRefNano: " + structRefNano + ",\n" + "biomeNano: " + biomeNano
+ ",\n" + "noiseNano: " + noiseNano + ",\n" + "surfaceNano: " + surfaceNano + ",\n" + "carverNano: "
+ carverNano + ",\n" + "featureNano: " + featureNano + ",\n" + "lightNano: " + lightNano + ",\n"
+ "endNano: " + endNano + "\n";
public String toString()
{
return "beginNano: " + beginNano + ",\n" +
"emptyNano: " + emptyNano + ",\n" +
"structStartNano: " + structStartNano + ",\n" +
"structRefNano: " + structRefNano + ",\n" +
"biomeNano: " + biomeNano + ",\n" +
"noiseNano: " + noiseNano + ",\n" +
"surfaceNano: " + surfaceNano + ",\n" +
"carverNano: " + carverNano + ",\n" +
"featureNano: " + featureNano + ",\n" +
"lightNano: " + lightNano + ",\n" +
"endNano: " + endNano + "\n";
}
}
public static class PerfCalculator {
public static final int SIZE = 10;
private int dataCount = 0;
public static class PerfCalculator
{
public static final int SIZE = 50;
Rolling totalTime = new Rolling(SIZE);
Rolling emptyTime = new Rolling(SIZE);
Rolling structStartTime = new Rolling(SIZE);
@@ -127,56 +130,65 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
Rolling featureTime = new Rolling(SIZE);
Rolling lightTime = new Rolling(SIZE);
Rolling lodTime = new Rolling(SIZE);
public void recordEvent(PrefEvent e) {
dataCount++;
public void recordEvent(PrefEvent e)
{
long preTime = e.beginNano;
totalTime.add(e.endNano - preTime);
if (e.emptyNano != 0) {
if (e.emptyNano != 0)
{
emptyTime.add(e.emptyNano - preTime);
preTime = e.emptyNano;
}
if (e.structStartNano != 0) {
if (e.structStartNano != 0)
{
structStartTime.add(e.structStartNano - preTime);
preTime = e.structStartNano;
}
if (e.structRefNano != 0) {
if (e.structRefNano != 0)
{
structRefTime.add(e.structRefNano - preTime);
preTime = e.structRefNano;
}
if (e.biomeNano != 0) {
if (e.biomeNano != 0)
{
biomeTime.add(e.biomeNano - preTime);
preTime = e.biomeNano;
}
if (e.noiseNano != 0) {
if (e.noiseNano != 0)
{
noiseTime.add(e.noiseNano - preTime);
preTime = e.noiseNano;
}
if (e.surfaceNano != 0) {
if (e.surfaceNano != 0)
{
surfaceTime.add(e.surfaceNano - preTime);
preTime = e.surfaceNano;
}
if (e.carverNano != 0) {
if (e.carverNano != 0)
{
carverTime.add(e.carverNano - preTime);
preTime = e.carverNano;
}
if (e.featureNano != 0) {
if (e.featureNano != 0)
{
featureTime.add(e.featureNano - preTime);
preTime = e.featureNano;
}
if (e.lightNano != 0) {
if (e.lightNano != 0)
{
lightTime.add(e.lightNano - preTime);
preTime = e.lightNano;
}
if (e.endNano != 0) {
if (e.endNano != 0)
{
lodTime.add(e.endNano - preTime);
preTime = e.endNano;
}
}
public String toString() {
if (dataCount < SIZE)
return "Pref Calculator collecting samples...";
public String toString()
{
return "Total: " + Duration.ofNanos((long) totalTime.getAverage()) + ", Empty/LoadChunk: "
+ Duration.ofNanos((long) emptyTime.getAverage()) + ", StructStart: "
+ Duration.ofNanos((long) structStartTime.getAverage()) + ", StructRef: "
@@ -190,56 +202,41 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
+ Duration.ofNanos((long) lodTime.getAverage());
}
}
public static final int TIMEOUT_SECONDS = 60;
// =================Generation Step===================
public static final int TIMEOUT_SECONDS = 30;
//=================Generation Step===================
public final LinkedList<GenerationEvent> events = new LinkedList<GenerationEvent>();
public final GlobalParameters params;
public final StepStructureStart stepStructureStart = new StepStructureStart(this);
public final StepStructureReference stepStructureReference = new StepStructureReference();
public final StepStructureReference stepStructureReference = new StepStructureReference(this);
public final StepBiomes stepBiomes = new StepBiomes(this);
public final StepNoise stepNoise = new StepNoise(this);
public final StepSurface stepSurface = new StepSurface(this);
public final StepFeatures stepFeatures = new StepFeatures(this);
public final StepLight stepLight = new StepLight(this);
public boolean unsafeThreadingRecorded = false;
static private final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
public static final long EXCEPTION_TIMER_RESET_TIME = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
public static final int EXCEPTION_COUNTER_TRIGGER = 20;
public int unknownExceptionCount = 0;
public long lastExceptionTriggerTime = 0;
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public static final LodThreadFactory threadFactory = new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY);
public ExecutorService executors = Executors.newFixedThreadPool(
CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads(), threadFactory);
public <T> T joinSync(CompletableFuture<T> f) {
if (!unsafeThreadingRecorded && !f.isDone()) {
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons: Unsafe Threading in Chunk Generator Detected!");
MC.sendChatMessage("\u00A7eTo increase stability, it is recommended to set world generation threads count to 1.");
ApiShared.LOGGER.error("Unsafe Threading in Chunk Generator: ", new RuntimeException("Concurrent future"));
unsafeThreadingRecorded = true;
}
return f.join();
}
@Override
public void resizeThreadPool(int newThreadCount) {
public void resizeThreadPool(int newThreadCount)
{
executors = Executors.newFixedThreadPool(newThreadCount,
new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY));
}
@Override
public boolean tryAddPoint(int px, int pz, int range, Steps target, boolean genAllDetails) {
public boolean tryAddPoint(int px, int pz, int range, Steps target, boolean genAllDetails)
{
int boxSize = range * 2 + 1;
int x = Math.floorDiv(px, boxSize) * boxSize + range;
int z = Math.floorDiv(pz, boxSize) * boxSize + range;
for (GenerationEvent event : events) {
for (GenerationEvent event : events)
{
if (event.tooClose(x, z, range))
return false;
}
@@ -247,142 +244,155 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
events.add(new GenerationEvent(new ChunkPos(x, z), range, this, target, genAllDetails));
return true;
}
@Override
public void updateAllFutures() {
if (unknownExceptionCount > 0) {
if (System.nanoTime() - lastExceptionTriggerTime >= EXCEPTION_TIMER_RESET_TIME) {
unknownExceptionCount = 0;
}
}
public void updateAllFutures()
{
// Update all current out standing jobs
Iterator<GenerationEvent> iter = events.iterator();
while (iter.hasNext()) {
while (iter.hasNext())
{
GenerationEvent event = iter.next();
if (event.isCompleted()) {
try {
if (event.isCompleted())
{
try
{
event.join();
} catch (Throwable e) {
ApiShared.LOGGER.error("Batching World Generator: Event {} gotten an exception", event);
ApiShared.LOGGER.error("Exception: ", e);
unknownExceptionCount++;
lastExceptionTriggerTime = System.nanoTime();
} finally {
}
catch (Throwable e)
{
e.printStackTrace();
while (e.getCause() != null)
{
e = e.getCause();
e.printStackTrace();
}
}
finally
{
iter.remove();
}
} else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
ApiShared.LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
ApiShared.LOGGER.info("Dump PrefEvent: " + event.pEvent);
try {
}
else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS))
{
ClientApi.LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
ClientApi.LOGGER.info("Dump PrefEvent: " + event.pEvent);
try
{
if (!event.terminate())
ApiShared.LOGGER.error("Failed to terminate the stuck generation event!");
} finally {
ClientApi.LOGGER.error("Failed to terminate the stuck generation event!");
}
finally
{
iter.remove();
}
}
}
if (unknownExceptionCount > EXCEPTION_COUNTER_TRIGGER) {
try {
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons: Too many exceptions in Batching World Generator! Disabling the generator.");
} catch (Exception e) {}
ApiShared.LOGGER.error("Too many exceptions in Batching World Generator! Now disabling.");
unknownExceptionCount = 0;
CONFIG.client().worldGenerator().setEnableDistantGeneration(false);
}
}
public BatchGenerationEnvironment(IWorldWrapper serverlevel, LodBuilder lodBuilder, LodDimension lodDim) {
public BatchGenerationEnvironment(IWorldWrapper serverlevel, LodBuilder lodBuilder, LodDimension lodDim)
{
super(serverlevel, lodBuilder, lodDim);
ApiShared.LOGGER.info("================WORLD_GEN_STEP_INITING=============");
ChunkGenerator generator = ((WorldWrapper) serverlevel).getServerWorld().getChunkSource().getGenerator();
if (!(generator instanceof NoiseBasedChunkGenerator ||
generator instanceof DebugLevelSource ||
generator instanceof FlatLevelSource)) {
MC.sendChatMessage("\u00A74\u00A7l\u00A7uWARNING: Distant Horizons: Unknown Chunk Generator Detected! Distant Generation May Fail!");
MC.sendChatMessage("\u00A7eIf it does crash, set Distant Generation to OFF or Generation Mode to None.");
ApiShared.LOGGER.warn("Unknown Chunk Generator detected: {}", generator.getClass());
}
ClientApi.LOGGER.info("================WORLD_GEN_STEP_INITING=============");
params = new GlobalParameters((ServerLevel) ((WorldWrapper) serverlevel).getWorld(), lodBuilder, lodDim);
}
@SuppressWarnings("resource")
private static ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, ServerLevel level, LevelLightEngine lightEngine) {
if (DISABLE_LOADING_SAVES) {
return new ProtoChunk(chunkPos, UpgradeData.EMPTY);
}
CompoundTag chunkData = null;
try {
chunkData = level.getChunkSource().chunkMap.readChunk(chunkPos);
} catch (Exception e) {
ApiShared.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
}
if (chunkData == null) {
return new ProtoChunk(chunkPos, UpgradeData.EMPTY);
} else {
try {
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
} catch (Exception e) {
ApiShared.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
return new ProtoChunk(chunkPos, UpgradeData.EMPTY);
}
}
public void startLoadingAllRegionsFromFile(LodDimension lodDim)
{
ServerLevel level = params.level;
level.getChunkSource();
}
void generateLodFromList(GenerationEvent e) {
@SuppressWarnings("resource")
public static ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, ServerLevel level, LevelLightEngine lightEngine)
{
CompoundTag chunkData = null;
try
{
chunkData = level.getChunkSource().chunkMap.readChunk(chunkPos);
}
catch (IOException e)
{
ClientApi.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
}
if (chunkData == null)
{
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level);
}
else
{
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
}
}
public void generateLodFromList(GenerationEvent e)
{
if (ENABLE_EVENT_LOGGING)
ApiShared.LOGGER.info("Lod Generate Event: " + e.pos);
ClientApi.LOGGER.info("Lod Generate Event: " + e.pos);
e.pEvent.beginNano = System.nanoTime();
GridList<ChunkAccess> referencedChunks;
DistanceGenerationMode generationMode;
LightedWorldGenRegion region;
WorldGenLevelLightEngine lightEngine;
LightGetterAdaptor adaptor;
try {
try
{
adaptor = new LightGetterAdaptor(params.level);
lightEngine = new WorldGenLevelLightEngine(adaptor);
int cx = e.pos.x;
int cy = e.pos.z;
int rangeEmpty = e.range + 1;
GridList<ChunkAccess> chunks = new GridList<ChunkAccess>(rangeEmpty);
@SuppressWarnings("resource")
EmptyChunkGenerator generator = (int x, int z) -> {
EmptyChunkGenerator generator = (int x, int z) ->
{
ChunkPos chunkPos = new ChunkPos(x, z);
ChunkAccess target = null;
try {
try
{
target = loadOrMakeChunk(chunkPos, params.level, lightEngine);
} catch (RuntimeException e2) {
}
catch (RuntimeException e2)
{
// Continue...
e2.printStackTrace();
}
if (target == null)
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY);
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY, params.level);
return target;
};
for (int oy = -rangeEmpty; oy <= rangeEmpty; oy++) {
for (int ox = -rangeEmpty; ox <= rangeEmpty; ox++) {
for (int oy = -rangeEmpty; oy <= rangeEmpty; oy++)
{
for (int ox = -rangeEmpty; ox <= rangeEmpty; ox++)
{
ChunkAccess target = generator.generate(cx + ox, cy + oy);
chunks.add(target);
}
}
e.pEvent.emptyNano = System.nanoTime();
e.refreshTimeout();
region = new LightedWorldGenRegion(params.level, lightEngine, e.tParam.structFeat, chunks,
ChunkStatus.STRUCTURE_STARTS, rangeEmpty, e.lightMode, generator);
region = new LightedWorldGenRegion(params.level, lightEngine, e.tParam.structFeat, chunks, ChunkStatus.STRUCTURE_STARTS, rangeEmpty, e.lightMode, generator);
adaptor.setRegion(region);
e.tParam.makeStructFeat(region);
referencedChunks = chunks.subGrid(e.range);
referencedChunks = generateDirect(e, referencedChunks, e.target, region);
} catch (StructStartCorruptedException f) {
}
catch (StepStructureStart.StructStartCorruptedException f)
{
e.tParam.markAsInvalid();
return;
}
switch (e.target) {
switch (e.target)
{
case Empty:
case StructureStart:
case StructureReference:
@@ -390,7 +400,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
break;
case Biomes:
generationMode = DistanceGenerationMode.BIOME_ONLY;
break;
case Noise:
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
break;
@@ -407,43 +416,62 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
return;
}
int centreIndex = referencedChunks.size() / 2;
for (int oy = -e.range; oy <= e.range; oy++) {
for (int ox = -e.range; ox <= e.range; ox++) {
for (int oy = -e.range; oy <= e.range; oy++)
{
for (int ox = -e.range; ox <= e.range; ox++)
{
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
ChunkAccess target = referencedChunks.get(targetIndex);
target.setLightCorrect(true);
//if (target instanceof LevelChunk)
// ((LevelChunk) target).setClientLightReady(true);
boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk;
if (isFull) {
//boolean isPartial = target.isOldNoiseGeneration();
if (isFull)
{
if (ENABLE_LOAD_EVENT_LOGGING)
ApiShared.LOGGER.info("Detected full existing chunk at {}", target.getPos());
ClientApi.LOGGER.info("Detected full existing chunk at {}", target.getPos());
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
new LodBuilderConfig(DistanceGenerationMode.FULL), true, e.genAllDetails);
} else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == DistanceGenerationMode.NONE) {
}
else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == DistanceGenerationMode.NONE)
{
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
LodBuilderConfig.getFillVoidConfig(), true, e.genAllDetails);
} else {
}
else
{
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
new LodBuilderConfig(generationMode), true, e.genAllDetails);
}
lightEngine.retainData(target.getPos(), false);
if (e.lightMode == LightGenerationMode.FANCY || isFull)
{
lightEngine.retainData(target.getPos(), false);
}
}
}
e.pEvent.endNano = System.nanoTime();
e.refreshTimeout();
if (ENABLE_PERF_LOGGING) {
if (ENABLE_PERF_LOGGING)
{
e.tParam.perf.recordEvent(e.pEvent);
ApiShared.LOGGER.info(e.tParam.perf);
ClientApi.LOGGER.info(e.tParam.perf);
}
}
GridList<ChunkAccess> generateDirect(GenerationEvent e, GridList<ChunkAccess> subRange, Steps step,
LightedWorldGenRegion region) {
try {
subRange.forEach((chunk) -> {
if (chunk instanceof ProtoChunk) {
public GridList<ChunkAccess> generateDirect(GenerationEvent e, GridList<ChunkAccess> subRange, Steps step,
LightedWorldGenRegion region)
{
try
{
subRange.forEach((chunk) ->
{
if (chunk instanceof ProtoChunk)
{
((ProtoChunk) chunk).setLightEngine(region.getLightEngine());
//region.getLightEngine().retainData(chunk.getPos(), true);
region.getLightEngine().retainData(chunk.getPos(), true);
}
});
if (step == Steps.Empty)
@@ -479,13 +507,17 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
e.pEvent.featureNano = System.nanoTime();
e.refreshTimeout();
return subRange;
} finally {
switch (region.lightMode) {
}
finally
{
switch (region.lightMode)
{
case FANCY:
stepLight.generateGroup(region.getLightEngine(), subRange);
break;
case FAST:
subRange.forEach((p) -> {
subRange.forEach((p) ->
{
if (p instanceof ProtoChunk)
((ProtoChunk) p).setLightCorrect(true);
});
@@ -495,8 +527,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
e.refreshTimeout();
}
}
public interface EmptyChunkGenerator {
public interface EmptyChunkGenerator
{
ChunkAccess generate(int x, int z);
}
@@ -507,16 +540,14 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
@Override
public void stop(boolean blocking) {
ApiShared.LOGGER.info("Batch Chunk Generator shutting down...");
ClientApi.LOGGER.info("Batch Chunk Generator shutting down...");
executors.shutdownNow();
if (blocking) {
try {
if (!executors.awaitTermination(10, TimeUnit.SECONDS)) {
ApiShared.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...");
}
} catch (InterruptedException e) {
ApiShared.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...", e);
if (blocking) try {
if (!executors.awaitTermination(10, TimeUnit.SECONDS)) {
ClientApi.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...");
}
} catch (InterruptedException e) {
ClientApi.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...", e);
}
}
}
}
@@ -1,3 +1,4 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import java.util.concurrent.ExecutionException;
@@ -5,19 +6,19 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PrefEvent;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.config.LightGenerationMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper.Steps;
import net.minecraft.world.level.ChunkPos;
//======================= Main Event class======================
public final class GenerationEvent {
public final class GenerationEvent
{
static private final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static int generationFutureDebugIDs = 0;
final ThreadedParameters tParam;
final ChunkPos pos;
@@ -29,8 +30,9 @@ public final class GenerationEvent {
final LightGenerationMode lightMode;
final PrefEvent pEvent = new PrefEvent();
final boolean genAllDetails;
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup, Steps target, boolean genAllDetails) {
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup, Steps target, boolean genAllDetails)
{
nanotime = System.nanoTime();
this.pos = pos;
this.range = range;
@@ -38,54 +40,65 @@ public final class GenerationEvent {
this.target = target;
this.tParam = ThreadedParameters.getOrMake(generationGroup.params);
LightGenerationMode mode = CONFIG.client().worldGenerator().getLightGenerationMode();
this.lightMode = mode;
this.genAllDetails = genAllDetails;
future = generationGroup.executors.submit(() -> {
future = generationGroup.executors.submit(() ->
{
generationGroup.generateLodFromList(this);
});
}
public boolean isCompleted() {
public boolean isCompleted()
{
return future.isDone();
}
public boolean hasTimeout(int duration, TimeUnit unit) {
public boolean hasTimeout(int duration, TimeUnit unit)
{
long currentTime = System.nanoTime();
long delta = currentTime - nanotime;
return (delta > TimeUnit.NANOSECONDS.convert(duration, unit));
}
public boolean terminate() {
public boolean terminate()
{
future.cancel(true);
ApiShared.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
ClientApi.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
BatchGenerationEnvironment.threadFactory.dumpAllThreadStacks();
return future.isCancelled();
}
public void join() {
try {
public void join()
{
try
{
future.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e.getCause()==null? e : e.getCause());
}
catch (InterruptedException | ExecutionException e)
{
e.printStackTrace();
}
}
public boolean tooClose(int cx, int cz, int cr) {
public boolean tooClose(int cx, int cz, int cr)
{
int distX = Math.abs(cx - pos.x);
int distZ = Math.abs(cz - pos.z);
int minRange = cr + range + 1; // Need one to account for the center
minRange += 1 + 1; // Account for required empty chunks
return distX < minRange && distZ < minRange;
}
public void refreshTimeout() {
public void refreshTimeout()
{
nanotime = System.nanoTime();
}
@Override
public String toString() {
public String toString()
{
return id + ":" + range + "@" + pos + "(" + target + ")";
}
}
@@ -1,3 +1,4 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import com.mojang.datafixers.DataFixer;
@@ -15,9 +16,11 @@ import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.storage.WorldData;
public final class GlobalParameters {
public final class GlobalParameters
{
public final ChunkGenerator generator;
public final StructureManager structures;
//public final BiomeManager biomeManager;
public final WorldGenSettings worldGenSettings;
public final ThreadedLevelLightEngine lightEngine;
public final LodBuilder lodBuilder;
@@ -27,8 +30,9 @@ public final class GlobalParameters {
public final long worldSeed;
public final ServerLevel level; // TODO: Figure out a way to remove this. Maybe ClientLevel also works?
public final DataFixer fixerUpper;
public GlobalParameters(ServerLevel level, LodBuilder lodBuilder, LodDimension lodDim) {
public GlobalParameters(ServerLevel level, LodBuilder lodBuilder, LodDimension lodDim)
{
this.lodBuilder = lodBuilder;
this.lodDim = lodDim;
this.level = level;
@@ -39,8 +43,7 @@ public final class GlobalParameters {
registry = server.registryAccess();
biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
worldSeed = worldGenSettings.seed();
// biomeManager = new BiomeManager(level,
// BiomeManager.obfuscateSeed(worldSeed));
//biomeManager = new BiomeManager(level, BiomeManager.obfuscateSeed(worldSeed));
structures = server.getStructureManager();
generator = level.getChunkSource().getGenerator();
fixerUpper = server.getFixerUpper();
@@ -1,29 +1,34 @@
package com.seibel.lod.common.wrappers.worldGeneration;
//FIXME: Move this outside the WorldGenerationStep thingy
public class Rolling {
public class Rolling
{
private final int size;
private double total = 0d;
private int index = 0;
private final double[] samples;
public Rolling(int size) {
public Rolling(int size)
{
this.size = size;
samples = new double[size];
for (int i = 0; i < size; i++)
samples[i] = 0d;
}
public void add(double x) {
public void add(double x)
{
total -= samples[index];
samples[index] = x;
total += x;
if (++index == size)
index = 0; // cheaper than modulus
}
public double getAverage() {
public double getAverage()
{
return total / size;
}
}
@@ -1,11 +0,0 @@
package com.seibel.lod.common.wrappers.worldGeneration;
public class StructStartCorruptedException extends RuntimeException {
private static final long serialVersionUID = -8987434342051563358L;
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e) {
super("StructStartCorruptedException");
super.initCause(e);
fillInStackTrace();
}
}
@@ -1,3 +1,4 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PerfCalculator;
@@ -7,14 +8,16 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.levelgen.WorldGenSettings;
public final class ThreadedParameters {
public final class ThreadedParameters
{
private static final ThreadLocal<ThreadedParameters> localParam = new ThreadLocal<ThreadedParameters>();
final ServerLevel level;
public final WorldGenStructFeatManager structFeat;
boolean isValid = true;
public final PerfCalculator perf = new PerfCalculator();
public static ThreadedParameters getOrMake(GlobalParameters param) {
public static ThreadedParameters getOrMake(GlobalParameters param)
{
ThreadedParameters tParam = localParam.get();
if (tParam != null && tParam.isValid && tParam.level == param.level)
return tParam;
@@ -22,17 +25,20 @@ public final class ThreadedParameters {
localParam.set(tParam);
return tParam;
}
public void markAsInvalid() {
public void markAsInvalid()
{
isValid = false;
}
private ThreadedParameters(GlobalParameters param) {
private ThreadedParameters(GlobalParameters param)
{
level = param.level;
structFeat = new WorldGenStructFeatManager(level, param.worldGenSettings, null);
}
public void makeStructFeat(WorldGenLevel genLevel) {
public void makeStructFeat(WorldGenLevel genLevel)
{
structFeat.setGenLevel(genLevel);
}
}
@@ -1,12 +1,10 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import java.util.concurrent.ExecutionException;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.objects.lod.LodDimension;
//import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
//import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
//import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
@@ -14,131 +12,141 @@ import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGenera
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.common.wrappers.world.WorldWrapper;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.*;
/**
* @author James Seibel
* @version 11-13-2021
*/
public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper {
public final ServerLevel serverWorld;
public final LodDimension lodDim;
public final LodBuilder lodBuilder;
public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper
{
public final ServerLevel serverWorld;
public final LodDimension lodDim;
public final LodBuilder lodBuilder;
public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
super(newLodBuilder, newLodDimension, worldWrapper);
public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
{
super(newLodBuilder, newLodDimension, worldWrapper);
lodBuilder = newLodBuilder;
lodDim = newLodDimension;
serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
}
lodBuilder = newLodBuilder;
lodDim = newLodDimension;
serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
}
/** takes about 2-5 ms */
@Override
public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode) {
generate(pos.getX(), pos.getZ(), generationMode);
}
/** takes about 10 - 20 ms */
@Override
public void generateSurface(AbstractChunkPosWrapper pos) {
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.SURFACE);
}
/** takes about 2-5 ms */
@Override
public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode)
{
generate(pos.getX(), pos.getZ(), generationMode);
}
/**
* takes about 15 - 20 ms
* <p>
*/
@Override
public void generateFeatures(AbstractChunkPosWrapper pos) {
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FEATURES);
}
/**
* Generates using MC's ServerWorld.
* <p>
* on pre generated chunks 0 - 1 ms <br>
* on un generated chunks 0 - 50 ms <br>
* with the median seeming to hover around 15 - 30 ms <br>
* and outliers in the 100 - 200 ms range <br>
* <p>
* Note this should not be multithreaded and does cause server/simulation lag
* (Higher lag for generating than loading)
*/
@Override
public void generateFull(AbstractChunkPosWrapper pos) {
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FULL);
}
/** takes about 10 - 20 ms */
@Override
public void generateSurface(AbstractChunkPosWrapper pos)
{
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.SURFACE);
}
private void generate(int chunkX, int chunkZ, DistanceGenerationMode generationMode) {
/**
* takes about 15 - 20 ms
* <p>
*/
@Override
public void generateFeatures(AbstractChunkPosWrapper pos)
{
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FEATURES);
}
/**
* Generates using MC's ServerWorld.
* <p>
* on pre generated chunks 0 - 1 ms <br>
* on un generated chunks 0 - 50 ms <br>
* with the median seeming to hover around 15 - 30 ms <br>
* and outliers in the 100 - 200 ms range <br>
* <p>
* Note this should not be multithreaded and does cause server/simulation lag
* (Higher lag for generating than loading)
*/
@Override
public void generateFull(AbstractChunkPosWrapper pos)
{
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FULL);
}
private void generate(int chunkX, int chunkZ, DistanceGenerationMode generationMode) {
// long t = System.nanoTime();
ChunkStatus targetStatus;
switch (generationMode) {
case NONE:
return;
ChunkStatus targetStatus;
switch (generationMode) {
case BIOME_ONLY:
targetStatus = ChunkStatus.BIOMES;
break;
case BIOME_ONLY_SIMULATE_HEIGHT:
targetStatus = ChunkStatus.NOISE;
break;
case SURFACE:
targetStatus = ChunkStatus.SURFACE;
break;
case FEATURES:
targetStatus = ChunkStatus.FEATURES;
break;
case FULL:
targetStatus = ChunkStatus.FULL;
break;
targetStatus = ChunkStatus.BIOMES;
break;
case BIOME_ONLY_SIMULATE_HEIGHT:
targetStatus = ChunkStatus.NOISE;
break;
case SURFACE:
targetStatus = ChunkStatus.SURFACE;
break;
case FEATURES:
targetStatus = ChunkStatus.FEATURES;
break;
case FULL:
targetStatus = ChunkStatus.FULL;
break;
case NONE:
default:
return;
}
return;
}
// The bool=true means that we wants to generate chunk, and that the returned
// ChunkAccess must not be null
// The bool=true means that we want to generate chunk, and that the returned ChunkAccess must not be null
ChunkAccess ca = serverWorld.getChunkSource().getChunk(chunkX, chunkZ, targetStatus, true);
if (ca == null)
throw new RuntimeException("This should NEVER be null due to bool being true");
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(ca, serverWorld),
new LodBuilderConfig(generationMode), false, true);
ChunkAccess ca = serverWorld.getChunkSource().getChunk(chunkX, chunkZ, targetStatus, true);
if (ca == null) throw new RuntimeException("This should NEVER be null due to bool being true");
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(ca, serverWorld), new LodBuilderConfig(generationMode), false, true);
// long duration = System.nanoTime()-t;
// long duration = System.nanoTime()-t;
// Debug print the duration
// System.out.println("LodChunkGenFull["+chunkX+","+chunkZ+"]:
// "+(double)(duration)/1000.);
}
// Debug print the duration
// System.out.println("LodChunkGenFull["+chunkX+","+chunkZ+"]: "+(double)(duration)/1000.);
}
/*
* TODO: Ask leetom to update chart performance/generation tests related to
/* TODO: Ask leetom to update chart
* performance/generation tests related to
* serverWorld.getChunk(x, z, ChunkStatus. *** )
*
* true/false is whether they generated blocks or not the time is how long it
* took to generate
*
* ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
* ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates
* some chunks) ChunkStatus.BIOMES 1 - 10 ms false (no height) ChunkStatus.NOISE
* 4 - 15 ms true (all blocks are stone) ChunkStatus.LIQUID_CARVERS 6 - 12 ms
* true (no snow/trees, just grass) ChunkStatus.SURFACE 5 - 15 ms true (no
* snow/trees, just grass) ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees,
* just grass) ChunkStatus.FEATURES 7 - 25 ms true ChunkStatus.HEIGHTMAPS 20 -
* 40 ms true ChunkStatus.LIGHT 20 - 40 ms true ChunkStatus.FULL 30 - 50 ms true
* ChunkStatus.SPAWN 50 - 80 ms true
*
*
* At this point I would suggest using FEATURES, as it generates snow and trees
* (and any other object that are needed to make biomes distinct)
*
* Otherwise, if snow/trees aren't necessary SURFACE is the next fastest
* (although not by much)
true/false is whether they generated blocks or not
the time is how long it took to generate
ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates some chunks)
ChunkStatus.BIOMES 1 - 10 ms false (no height)
ChunkStatus.NOISE 4 - 15 ms true (all blocks are stone)
ChunkStatus.LIQUID_CARVERS 6 - 12 ms true (no snow/trees, just grass)
ChunkStatus.SURFACE 5 - 15 ms true (no snow/trees, just grass)
ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees, just grass)
ChunkStatus.FEATURES 7 - 25 ms true
ChunkStatus.HEIGHTMAPS 20 - 40 ms true
ChunkStatus.LIGHT 20 - 40 ms true
ChunkStatus.FULL 30 - 50 ms true
ChunkStatus.SPAWN 50 - 80 ms true
At this point I would suggest using FEATURES, as it generates snow and trees
(and any other object that are needed to make biomes distinct)
Otherwise, if snow/trees aren't necessary SURFACE is the next fastest (although not by much)
*/
}
@@ -1,7 +1,6 @@
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import java.util.Objects;
@@ -17,7 +16,6 @@ import net.minecraft.world.level.TickList;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.DataLayer;
import net.minecraft.world.level.chunk.LevelChunk;
@@ -32,13 +30,14 @@ import net.minecraft.world.level.material.Fluids;
import org.apache.logging.log4j.Logger;
public class ChunkLoader {
private static final Logger LOGGER = ApiShared.LOGGER;
private static final Logger LOGGER = ClientApi.LOGGER;
private static LevelChunkSection[] readSections(WorldGenLevel level, LevelLightEngine lightEngine,
ChunkPos chunkPos, CompoundTag tagLevel) {
boolean isLightOn = tagLevel.getBoolean("isLightOn");
ListTag listTag = tagLevel.getList("Sections", 10);
LevelChunkSection[] levelChunkSections = new LevelChunkSection[16];
int i = level.getSectionsCount();
LevelChunkSection[] levelChunkSections = new LevelChunkSection[i];
boolean bl2 = level.getLevel().dimensionType().hasSkyLight();
if (isLightOn)
lightEngine.retainData(chunkPos, true);
@@ -51,7 +50,7 @@ public class ChunkLoader {
compoundTag3.getLongArray("BlockStates"));
levelChunkSection.recalcBlockCounts();
if (!levelChunkSection.isEmpty())
levelChunkSections[k] = levelChunkSection;
levelChunkSections[level.getSectionIndexFromSectionY(k)] = levelChunkSection;
}
if (isLightOn) {
if (compoundTag3.contains("BlockLight", 7))
@@ -110,25 +109,24 @@ public class ChunkLoader {
// ====================== Read params for making the LevelChunk
// ============================
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunkPos,
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), level, chunkPos,
level.getLevel().getChunkSource().getGenerator().getBiomeSource(),
tagLevel.contains("Biomes", 11) ? tagLevel.getIntArray("Biomes") : null);
UpgradeData upgradeData = tagLevel.contains("UpgradeData", 10)
? new UpgradeData(tagLevel.getCompound("UpgradeData"))
? new UpgradeData(tagLevel.getCompound("UpgradeData"), level)
: UpgradeData.EMPTY;
TickList<Block> blockTicks = tagLevel.contains("TileTicks", 9)
? ChunkTickList.create(tagLevel.getList("TileTicks", 10), Registry.BLOCK::getKey, Registry.BLOCK::get)
: new ProtoTickList<Block>(block -> (block == null || block.defaultBlockState().isAir()), chunkPos,
tagLevel.getList("ToBeTicked", 9));
tagLevel.getList("ToBeTicked", 9), level);
TickList<Fluid> liquidTicks = tagLevel.contains("LiquidTicks", 9)
? ChunkTickList.create(tagLevel.getList("LiquidTicks", 10), Registry.FLUID::getKey, Registry.FLUID::get)
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
tagLevel.getList("LiquidsToBeTicked", 9));
tagLevel.getList("LiquidsToBeTicked", 9), level);
long inhabitedTime = tagLevel.getLong("InhabitedTime");
@@ -1,9 +1,10 @@
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.api.ModAccessorApi;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LightChunkGetter;
@@ -14,7 +15,7 @@ public class LightGetterAdaptor implements LightChunkGetter {
public LightGetterAdaptor(BlockGetter heightAccessor) {
this.heightGetter = heightAccessor;
shouldReturnNull = ModAccessorHandler.get(IStarlightAccessor.class) != null;
shouldReturnNull = ModAccessorApi.get(IStarlightAccessor.class) != null;
}
public void setRegion(LightedWorldGenRegion region) {
@@ -33,4 +34,7 @@ public class LightGetterAdaptor implements LightChunkGetter {
public BlockGetter getLevel() {
return shouldReturnNull ? null : (genRegion != null ? genRegion : heightGetter);
}
public LevelHeightAccessor getLevelHeightAccessor() {
return heightGetter;
}
}
@@ -3,7 +3,6 @@ package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import java.util.List;
import java.util.stream.Stream;
import com.seibel.lod.core.api.ApiShared;
import org.jetbrains.annotations.Nullable;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.EmptyChunkGenerator;
@@ -46,18 +45,14 @@ public class LightedWorldGenRegion extends WorldGenRegion {
public void setOverrideCenter(ChunkPos pos) {overrideCenterPos = pos;}
@Override
public int getCenterX() {
return overrideCenterPos==null ? super.getCenterX() : overrideCenterPos.x;
}
@Override
public int getCenterZ() {
return overrideCenterPos==null ? super.getCenterZ() : overrideCenterPos.z;
public ChunkPos getCenter() {
return overrideCenterPos==null ? super.getCenter() : overrideCenterPos;
}
public LightedWorldGenRegion(ServerLevel serverLevel, WorldGenLevelLightEngine lightEngine,
StructureFeatureManager structFeat, List<ChunkAccess> list, ChunkStatus chunkStatus, int i,
LightGenerationMode lightMode, EmptyChunkGenerator generator) {
super(serverLevel, list);
super(serverLevel, list, chunkStatus, i);
this.lightMode = lightMode;
this.firstPos = list.get(0).getPos();
this.generator = generator;
@@ -68,6 +63,20 @@ public class LightedWorldGenRegion extends WorldGenRegion {
size = Mth.floor(Math.sqrt(list.size()));
}
// Bypass BCLib mixin overrides.
@Override
public boolean ensureCanWrite(BlockPos blockPos) {
int i = SectionPos.blockToSectionCoord(blockPos.getX());
int j = SectionPos.blockToSectionCoord(blockPos.getZ());
ChunkPos chunkPos = this.getCenter();
int k = Math.abs(chunkPos.x - i);
int l = Math.abs(chunkPos.z - j);
if (k > this.writeRadius || l > this.writeRadius) {
return false;
}
return true;
}
@Override
public Stream<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
StructureFeature<?> structureFeature) {
@@ -174,7 +183,7 @@ public class LightedWorldGenRegion extends WorldGenRegion {
}
}
if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus) {
ApiShared.LOGGER.info("WorldGen requiring " + chunkStatus
ClientApi.LOGGER.info("WorldGen requiring " + chunkStatus
+ " outside expected range detected. Force passing EMPTY chunk and seeing if it works.");
debugTriggeredForStatus = chunkStatus;
}
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.DataLayer;
@@ -16,149 +17,161 @@ import net.minecraft.world.level.lighting.SkyLightEngine;
public class WorldGenLevelLightEngine extends LevelLightEngine {
public static final int MAX_SOURCE_LEVEL = 15;
public static final int LIGHT_SECTION_PADDING = 1;
@Nullable
public final BlockLightEngine blockEngine;
@Nullable
public final SkyLightEngine skyEngine;
public static final int LIGHT_SECTION_PADDING = 1;
protected final LevelHeightAccessor levelHeightAccessor;
@Nullable
public final BlockLightEngine blockEngine;
@Nullable
public final SkyLightEngine skyEngine;
public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
super(genRegion, false, false);
this.blockEngine = new BlockLightEngine(genRegion);
this.skyEngine = new SkyLightEngine(genRegion);
}
public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
super(genRegion, false, false);
this.levelHeightAccessor = genRegion.getLevelHeightAccessor();
this.blockEngine = new BlockLightEngine(genRegion);
this.skyEngine = new SkyLightEngine(genRegion);
}
@Override
public void checkBlock(BlockPos blockPos) {
if (this.blockEngine != null) {
this.blockEngine.checkBlock(blockPos);
}
if (this.skyEngine != null) {
this.skyEngine.checkBlock(blockPos);
}
}
@Override
public void checkBlock(BlockPos blockPos) {
if (this.blockEngine != null) {
this.blockEngine.checkBlock(blockPos);
}
if (this.skyEngine != null) {
this.skyEngine.checkBlock(blockPos);
}
}
@Override
public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
if (this.blockEngine != null) {
this.blockEngine.onBlockEmissionIncrease(blockPos, i);
}
}
@Override
public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
if (this.blockEngine != null) {
this.blockEngine.onBlockEmissionIncrease(blockPos, i);
}
}
@Override
public boolean hasLightWork() {
if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
return true;
}
return this.blockEngine != null && this.blockEngine.hasLightWork();
}
@Override
public boolean hasLightWork() {
if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
return true;
}
return this.blockEngine != null && this.blockEngine.hasLightWork();
}
@Override
public int runUpdates(int i, boolean bl, boolean bl2) {
if (this.blockEngine != null && this.skyEngine != null) {
int j = i / 2;
int k = this.blockEngine.runUpdates(j, bl, bl2);
int l = i - j + k;
int m = this.skyEngine.runUpdates(l, bl, bl2);
if (k == 0 && m > 0) {
return this.blockEngine.runUpdates(m, bl, bl2);
}
return m;
}
if (this.blockEngine != null) {
return this.blockEngine.runUpdates(i, bl, bl2);
}
if (this.skyEngine != null) {
return this.skyEngine.runUpdates(i, bl, bl2);
}
return i;
}
@Override
public int runUpdates(int i, boolean bl, boolean bl2) {
if (this.blockEngine != null && this.skyEngine != null) {
int j = i / 2;
int k = this.blockEngine.runUpdates(j, bl, bl2);
int l = i - j + k;
int m = this.skyEngine.runUpdates(l, bl, bl2);
if (k == 0 && m > 0) {
return this.blockEngine.runUpdates(m, bl, bl2);
}
return m;
}
if (this.blockEngine != null) {
return this.blockEngine.runUpdates(i, bl, bl2);
}
if (this.skyEngine != null) {
return this.skyEngine.runUpdates(i, bl, bl2);
}
return i;
}
@Override
public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.updateSectionStatus(sectionPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.updateSectionStatus(sectionPos, bl);
}
}
@Override
public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.updateSectionStatus(sectionPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.updateSectionStatus(sectionPos, bl);
}
}
@Override
public void enableLightSources(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.enableLightSources(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.enableLightSources(chunkPos, bl);
}
}
@Override
public void enableLightSources(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.enableLightSources(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.enableLightSources(chunkPos, bl);
}
}
@Override
public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.blockEngine;
}
if (this.skyEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.skyEngine;
}
@Override
public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.blockEngine;
}
if (this.skyEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.skyEngine;
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
return Math.max(k, j);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
return Math.max(k, j);
}
public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
ChunkPos chunkPos = chunkAccess.getPos();
chunkAccess.setLightCorrect(false);
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
for (int i = 0; i < 16; i++) {
LevelChunkSection levelChunkSection = levelChunkSections[i];
public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
ChunkPos chunkPos = chunkAccess.getPos();
chunkAccess.setLightCorrect(false);
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
for (int i = 0; i < chunkAccess.getSectionsCount(); ++i) {
LevelChunkSection levelChunkSection = levelChunkSections[i];
if (!LevelChunkSection.isEmpty(levelChunkSection)) {
updateSectionStatus(SectionPos.of(chunkPos, i), false);
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
updateSectionStatus(SectionPos.of(chunkPos, j), false);
}
}
enableLightSources(chunkPos, true);
if (needLightBlockUpdate) {
chunkAccess.getLights()
.forEach(blockPos -> onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
}
}
enableLightSources(chunkPos, true);
if (needLightBlockUpdate) {
chunkAccess.getLights().forEach(blockPos ->
onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
}
chunkAccess.setLightCorrect(true);
}
chunkAccess.setLightCorrect(true);
}
@Override
public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer,
boolean bl) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine != null) {
this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
} else if (this.skyEngine != null) {
this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
}
@Override
public void retainData(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.retainData(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.retainData(chunkPos, bl);
}
}
@Override
public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer, boolean bl) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine != null) {
this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
} else if (this.skyEngine != null) {
this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
}
@Override
public void retainData(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.retainData(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.retainData(chunkPos, bl);
}
}
@Override
public int getLightSectionCount() {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMinLightSection() {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMaxLightSection() {
throw new UnsupportedOperationException("This should never be used!");
}
}
@@ -17,7 +17,6 @@ import net.minecraft.world.level.levelgen.structure.StructureStart;
public class WorldGenStructFeatManager extends StructureFeatureManager {
WorldGenLevel genLevel;
WorldGenSettings worldGenSettings;
public WorldGenStructFeatManager(LevelAccessor levelAccessor, WorldGenSettings worldGenSettings,
WorldGenLevel genLevel) {
super(levelAccessor, worldGenSettings);
@@ -27,7 +26,7 @@ public class WorldGenStructFeatManager extends StructureFeatureManager {
public void setGenLevel(WorldGenLevel genLevel) {
this.genLevel = genLevel;
}
}
@Override
public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion) {
@@ -1,7 +1,6 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.EnumSet;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
@@ -12,7 +11,6 @@ import net.minecraft.ReportedException;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.Heightmap;
public final class StepFeatures {
/**
@@ -42,7 +40,6 @@ public final class StepFeatures {
for (ChunkAccess chunk : chunksToDo) {
try {
worldGenRegion.setOverrideCenter(chunk.getPos());
Heightmap.primeHeightmaps(chunk, STATUS.heightmapsAfter());
envionment.params.generator.applyBiomeDecoration(worldGenRegion, tParams.structFeat);
} catch (ReportedException e) {
e.printStackTrace();
@@ -9,45 +9,46 @@ import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.lighting.LightEventListener;
public final class StepLight {
/**
*
*/
private final BatchGenerationEnvironment envionment;
private final BatchGenerationEnvironment environment;
/**
* @param worldGenerationEnvironment
* @param batchGenerationEnvironment
*/
public StepLight(BatchGenerationEnvironment worldGenerationEnvironment) {
envionment = worldGenerationEnvironment;
public StepLight(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.LIGHT;
public void generateGroup(LevelLightEngine lightEngine, GridList<ChunkAccess> chunks) {
// ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
public void generateGroup(LightEventListener lightEngine,
GridList<ChunkAccess> chunks) {
//ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
}
for (ChunkAccess chunk : chunks) {
boolean hasCorrectBlockLight = (chunk instanceof LevelChunk && chunk.isLightCorrect());
try {
if (lightEngine == null) {
// Do nothing
} else if (lightEngine instanceof WorldGenLevelLightEngine) {
((WorldGenLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
((WorldGenLevelLightEngine)lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
} else if (lightEngine instanceof ThreadedLevelLightEngine) {
((ThreadedLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight).join();
} else {
assert (false);
assert(false);
}
} catch (Exception e) {
e.printStackTrace();
}
@@ -1,45 +1,93 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.google.common.collect.Sets;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.core.QuartPos;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.util.Mth;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseSettings;
public final class StepNoise {
/**
*
*/
private final BatchGenerationEnvironment envionment;
private final BatchGenerationEnvironment environment;
/**
* @param worldGenerationEnvironment
* @param batchGenerationEnvironment
*/
public StepNoise(BatchGenerationEnvironment worldGenerationEnvironment) {
envionment = worldGenerationEnvironment;
public StepNoise(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
private static <T> T joinSync(CompletableFuture<T> f) {
if (!f.isDone()) throw new RuntimeException("The future is concurrent!");
return f.join();
}
public final ChunkStatus STATUS = ChunkStatus.NOISE;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List<ChunkAccess> chunks) {
private ChunkAccess NoiseBased$fillFromNoise(NoiseBasedChunkGenerator generator, StructureFeatureManager structureFeatureManager, ChunkAccess chunkAccess) {
NoiseSettings noiseSettings = generator.settings.get().noiseSettings();
int i = Math.max(noiseSettings.minY(), chunkAccess.getMinBuildHeight());
int j = Math.min(noiseSettings.minY() + noiseSettings.height(), chunkAccess.getMaxBuildHeight());
int cellHeight = QuartPos.toBlock(noiseSettings.noiseSizeVertical());
int k = Mth.intFloorDiv(i, cellHeight);
int l = Mth.intFloorDiv(j - i, cellHeight);
if (l <= 0) {
return chunkAccess;
}
int m = chunkAccess.getSectionIndex(l * cellHeight - 1 + i);
int n = chunkAccess.getSectionIndex(i);
HashSet<LevelChunkSection> set = Sets.newHashSet();
try {
for (int o = m; o >= n; --o) {
LevelChunkSection levelChunkSection = chunkAccess.getOrCreateSection(o);
levelChunkSection.acquire();
set.add(levelChunkSection);
}
chunkAccess = generator.doFill(structureFeatureManager, chunkAccess, k, l);
return chunkAccess;
} finally {
for (LevelChunkSection levelChunkSection : set) {
levelChunkSection.release();
};
}
}
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepNoise: "+chunk.getPos());
envionment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk);
if (environment.params.generator instanceof NoiseBasedChunkGenerator) {
chunk = NoiseBased$fillFromNoise((NoiseBasedChunkGenerator)environment.params.generator,
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
} else {
chunk = joinSync(environment.params.generator.fillFromNoise(Runnable::run,
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
}
}
}
}
@@ -3,8 +3,8 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
@@ -20,6 +20,19 @@ import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.structure.StructureStart;
public final class StepStructureReference {
/**
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
public StepStructureReference(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
private void createReferences(WorldGenRegion worldGenLevel, StructureFeatureManager structureFeatureManager,
@@ -30,7 +43,7 @@ public final class StepStructureReference {
int l = chunkPos.getMinBlockX();
int m = chunkPos.getMinBlockZ();
SectionPos sectionPos = SectionPos.of(chunkAccess.getPos(), 0);
SectionPos sectionPos = SectionPos.bottomOf(chunkAccess);
for (int n = j - 8; n <= j + 8; n++) {
for (int o = k - 8; o <= k + 8; o++) {
@@ -41,11 +54,12 @@ public final class StepStructureReference {
try {
if (structureStart.isValid()
&& structureStart.getBoundingBox().intersects(l, m, l + 15, m + 15)) {
structureFeatureManager.addReferenceForFeature(sectionPos, structureStart.getFeature(), p,
chunkAccess);
structureFeatureManager.addReferenceForFeature(sectionPos, structureStart.getFeature(),
p, chunkAccess);
}
} catch (Exception exception) {
CrashReport crashReport = CrashReport.forThrowable(exception, "Generating structure reference");
CrashReport crashReport = CrashReport.forThrowable(exception,
"Generating structure reference");
CrashReportCategory crashReportCategory = crashReport.addCategory("Structure");
crashReportCategory.setDetail("Id",
() -> Registry.STRUCTURE_FEATURE.getKey(structureStart.getFeature()).toString());
@@ -59,17 +73,17 @@ public final class StepStructureReference {
}
}
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List<ChunkAccess> chunks) {
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepStructureReference: "+chunk.getPos());
createReferences(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
@@ -3,8 +3,8 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.chunk.ChunkAccess;
@@ -15,33 +15,44 @@ public final class StepStructureStart {
/**
*
*/
private final BatchGenerationEnvironment envionment;
private final BatchGenerationEnvironment environment;
/**
* @param worldGenerationEnvironment
* @param batchGenerationEnvironment
*/
public StepStructureStart(BatchGenerationEnvironment worldGenerationEnvironment) {
envionment = worldGenerationEnvironment;
public StepStructureStart(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
public static class StructStartCorruptedException extends RuntimeException {
private static final long serialVersionUID = -8987434342051563358L;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List<ChunkAccess> chunks) {
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e) {
super("StructStartCorruptedException");
super.initCause(e);
fillInStackTrace();
}
}
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
if (envionment.params.worldGenSettings.generateFeatures()) {
if (environment.params.worldGenSettings.generateFeatures()) {
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepStructureStart: "+chunk.getPos());
envionment.params.generator.createStructures(envionment.params.registry, tParams.structFeat, chunk,
envionment.params.structures, envionment.params.worldSeed);
environment.params.generator.createStructures(environment.params.registry, tParams.structFeat, chunk, environment.params.structures,
environment.params.worldSeed);
}
}
}
@@ -3,8 +3,8 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.chunk.ChunkAccess;
@@ -15,30 +15,31 @@ public final class StepSurface {
/**
*
*/
private final BatchGenerationEnvironment envionment;
private final BatchGenerationEnvironment environment;
/**
* @param worldGenerationEnvironment
* @param batchGenerationEnvironment
*/
public StepSurface(BatchGenerationEnvironment worldGenerationEnvironment) {
envionment = worldGenerationEnvironment;
public StepSurface(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.SURFACE;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List<ChunkAccess> chunks) {
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepSurface: "+chunk.getPos());
envionment.params.generator.buildSurfaceAndBedrock(worldGenRegion, chunk);
environment.params.generator.buildSurfaceAndBedrock(worldGenRegion, chunk);
}
}
}
+20 -4
View File
@@ -4,10 +4,16 @@ accessWidener v1 named
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used when rendering
accessible field com/mojang/blaze3d/vertex/VertexBuffer indexCount I
accessible field com/mojang/blaze3d/vertex/VertexBuffer vertextBufferId I
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
# pre-render setup
accessible field net/minecraft/client/renderer/LevelRenderer renderChunks Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
# used for grabbing vanilla rendered chunks
accessible field net/minecraft/client/renderer/LevelRenderer renderChunks Lit/unimi/dsi/fastutil/objects/ObjectList;
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
@@ -19,6 +25,9 @@ accessible field net/minecraft/world/level/lighting/LevelLightEngine skyEngine L
# world generation
accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V
accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings;
accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Ljava/util/function/Supplier;
accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doFill (Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;II)Lnet/minecraft/world/level/chunk/ChunkAccess;
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
accessible field net/minecraft/world/level/chunk/ChunkGenerator biomeSource Lnet/minecraft/world/level/biome/BiomeSource;
@@ -27,7 +36,14 @@ accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/min
accessible method net/minecraft/server/level/ChunkMap readChunk (Lnet/minecraft/world/level/ChunkPos;)Lnet/minecraft/nbt/CompoundTag;
# grabbing textures
accessible field net/minecraft/client/renderer/block/model/BakedQuad sprite Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite framesX [I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite framesY [I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite animatedTexture Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture;
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite width I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite height I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite mainImage [Lcom/mojang/blaze3d/platform/NativeImage;
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameX (I)I
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameY (I)I
extendable class com/mojang/math/Matrix4f
# hacky stuff
accessible field net/minecraft/world/level/chunk/PalettedContainer lock Ljava/util/concurrent/Semaphore;
mutable field net/minecraft/world/level/chunk/PalettedContainer lock Ljava/util/concurrent/Semaphore;
+1 -1
Submodule core updated: 510058b7df...67f12c136c
+46 -10
View File
@@ -1,6 +1,5 @@
plugins {
id "com.github.johnrengelman.shadow" version "7.0.0"
id "com.modrinth.minotaur" version "1.2.1"
}
version = rootProject.mod_version+"-"+rootProject.minecraft_version+"-"+new Date().format("yyyy_MM_dd_HH_mm")
@@ -25,12 +24,6 @@ repositories {
maven { url "https://maven.terraformersmc.com/" }
}
def addMod(path, enabled) {
if (enabled == "2")
dependencies { modImplementation(path) }
else if (enabled == "1")
dependencies { modCompileOnly(path) }
}
dependencies {
// Fabric loader
@@ -45,14 +38,30 @@ dependencies {
}
// Sodium
addMod("curse.maven:sodium-394468:${rootProject.sodium_version}", rootProject.enable_sodium)
modImplementation "curse.maven:sodium-394468:${rootProject.sodium_version}"
implementation "org.joml:joml:1.10.2"
// Lithium
addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium)
// modImplementation "maven.modrinth:lithium:${rootProject.lithium_version}"
// Iris
addMod("maven.modrinth:iris:${rootProject.iris_version}", rootProject.enable_iris)
// modImplementation "maven.modrinth:iris:${rootProject.iris_version}"
// Immersive Portals
/*
modImplementation("com.github.qouteall.ImmersivePortalsMod:build:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.qouteall.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.qouteall.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
*/
@@ -96,8 +105,35 @@ runClient {
finalizedBy(deleteResources)
}
// Put stuff from gradle.properties into the mod info stuff
def resourceTargets = ["fabric.mod.json"]
def intoTargets = ["$buildDir/resources/main/"]
def replaceProperties = [
version: mod_version,
mod_name: mod_name,
authors: mod_authors,
description: mod_description
]
processResources {
dependsOn(copyAccessWidener)
inputs.properties replaceProperties
replaceProperties.put 'project', project
filesMatching(resourceTargets) {
expand replaceProperties
}
intoTargets.each { target ->
if (file(target).exists()) {
copy {
from(sourceSets.main.resources) {
include resourceTargets
expand replaceProperties
}
into target
}
}
}
}
shadowJar {
@@ -26,22 +26,15 @@ import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.common.wrappers.world.DimensionTypeWrapper;
import com.seibel.lod.common.wrappers.world.WorldWrapper;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.fabric.mixins.events.MixinClientLevel;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.fabricmc.fabric.mixin.event.lifecycle.client.ClientChunkManagerMixin;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientChunkCache;
import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.Level;
@@ -49,7 +42,6 @@ import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.chunk.LevelChunk;
import java.util.HashSet;
import java.util.List;
import org.lwjgl.glfw.GLFW;
@@ -74,6 +66,8 @@ public class ClientProxy
public void registerEvents() {
// TODO: Fix this if it's wrong
/* Registor the mod accessor*/
/* World Events */
//ServerTickEvents.START_SERVER_TICK.register(this::serverTickEvent);
ServerTickEvents.END_SERVER_TICK.register(this::serverTickEvent);
@@ -82,8 +76,6 @@ public class ClientProxy
//ServerChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
ClientChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
/* World Events */
ServerWorldEvents.LOAD.register((server, level) -> this.worldLoadEvent(level));
ServerWorldEvents.UNLOAD.register((server, level) -> this.worldUnloadEvent(level));
@@ -21,18 +21,16 @@ package com.seibel.lod.fabric;
import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.handlers.dependencyInjection.DependencyHandler;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.api.ModAccessorApi;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
import com.seibel.lod.fabric.wrappers.modAccessor.OptifineAccessor;
import com.seibel.lod.fabric.wrappers.modAccessor.SodiumAccessor;
import com.seibel.lod.fabric.wrappers.FabricDependencySetup;
import com.seibel.lod.fabric.wrappers.DependencySetup;
import net.fabricmc.api.ClientModInitializer;
@@ -45,9 +43,9 @@ import net.fabricmc.api.ClientModInitializer;
* @author Ran
* @version 12-1-2021
*/
public class FabricMain implements ClientModInitializer
public class Main implements ClientModInitializer
{
// This is a client mod so it should implement ClientModInitializer and in fabric.mod.json it should have "environment": "client"
// This is a client mod, so it should implement ClientModInitializer and in fabric.mod.json it should have "environment": "client"
// Once it works on servers change the implement to ModInitializer and in fabric.mod.json it should be "environment": "*"
public static ClientProxy client_proxy;
@@ -64,37 +62,25 @@ public class FabricMain implements ClientModInitializer
public static void init() {
LodCommonMain.initConfig();
LodCommonMain.startup(null, false);
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
// make sure the dependencies are set up before the mod needs them
FabricDependencySetup.createInitialBindings();
FabricDependencySetup.finishBinding();
// mod dependencies
if (SingletonHandler.get(IModChecker.class).isModLoaded("sodium")) {
ModAccessorHandler.bind(ISodiumAccessor.class, new SodiumAccessor());
}
if (SingletonHandler.get(IModChecker.class).isModLoaded("optifine")) {
ModAccessorHandler.bind(IOptifineAccessor.class, new OptifineAccessor());
}
ModAccessorHandler.finishBinding();
DependencySetup.createInitialBindings();
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
ClientApi.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
// Check if this works
client_proxy = new ClientProxy();
client_proxy.registerEvents();
if (SingletonHandler.get(IModChecker.class).isModLoaded("sodium")) {
ModAccessorApi.bind(ISodiumAccessor.class, new SodiumAccessor());
}
if (SingletonHandler.get(IModChecker.class).isModLoaded("optifine")) {
ModAccessorApi.bind(IOptifineAccessor.class, new OptifineAccessor());
}
}
public static void initServer() {
LodCommonMain.initConfig();
LodCommonMain.startup(null, true);
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
FabricDependencySetup.createInitialBindings();
FabricDependencySetup.finishBinding();
DependencySetup.createInitialBindings();
ClientApi.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
}
}
@@ -6,18 +6,15 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.FogRenderer.FogMode;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.FogType;
@Mixin(FogRenderer.class)
@@ -25,23 +22,19 @@ public class MixinFogRenderer {
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
private static final float A_REALLY_REALLY_BIG_VALUE = 4206942069.F;
private static final float A_EVEN_LARGER_VALUE = 420694206942069.F;
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("RETURN"), method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZ)V")
private static final void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback) {
FogType fogType = camera.getFluidInCamera();
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback) {
FogType fogTypes = camera.getFluidInCamera();
Entity entity = camera.getEntity();
boolean enableFog = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
enableFog |= fogType.equals(FogType.WATER);
enableFog |= fogType.equals(FogType.LAVA);
enableFog |= fogType.equals(FogType.POWDER_SNOW);
if (!enableFog) {
if (fogMode == FogMode.FOG_TERRAIN && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
boolean isUnderWater = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
if (!isUnderWater) {
if (fogMode == FogMode.FOG_TERRAIN && fogTypes == FogType.NONE && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
}
}
}
}
}
@@ -1,6 +1,6 @@
package com.seibel.lod.fabric.mixins;
import com.seibel.lod.fabric.FabricMain;
import com.seibel.lod.fabric.Main;
import net.minecraft.client.Minecraft;
import net.minecraft.client.main.GameConfig;
import org.spongepowered.asm.mixin.Mixin;
@@ -16,6 +16,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public class MixinMinecraft {
@Inject(method = "<init>", at = @At("TAIL"))
private void startMod(GameConfig gameConfig, CallbackInfo ci) {
FabricMain.init();
Main.init();
}
}
@@ -3,7 +3,7 @@ package com.seibel.lod.fabric.mixins;
import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.common.wrappers.config.TexturedButtonWidget;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.gui.screens.OptionsScreen;
import net.minecraft.client.gui.screens.Screen;
@@ -34,7 +34,7 @@ public class MixinOptionsScreen extends Screen {
@Inject(at = @At("HEAD"),method = "init")
private void lodconfig$init(CallbackInfo ci) {
if (SingletonHandler.get(ILodConfigWrapperSingleton.class).client().getOptionsButton())
this.addButton(new TexturedButtonWidget(
this.addRenderableWidget(new TexturedButtonWidget(
// Where the button is on the screen
this.width / 2 - 180, this.height / 6 - 12,
// Width and height of the button
@@ -20,19 +20,17 @@
package com.seibel.lod.fabric.mixins;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;
import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.client.renderer.LevelRenderer;
import org.lwjgl.opengl.GL15;
import net.minecraft.client.renderer.RenderType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.client.renderer.RenderType;
/**
* This class is used to mix in my rendering code
* before Minecraft starts rendering blocks.
@@ -49,35 +47,28 @@ import net.minecraft.client.renderer.RenderType;
@Mixin(LevelRenderer.class)
public class MixinWorldRenderer
{
// TODO: Fix clouds
private static float previousPartialTicks = 0;
public MixinWorldRenderer() {
throw new NullPointerException("Null cannot be cast to non-null type.");
}
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/vertex/PoseStack;F)V")
private void renderSky(PoseStack matrixStackIn, float partialTicks, CallbackInfo callback)
{
// get the partial ticks since renderBlockLayer doesn't
@Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true)
public void renderClouds(PoseStack poseStack, Matrix4f projectionMatrix, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) {
// get the partial ticks since renderChunkLayer doesn't
// have access to them
previousPartialTicks = partialTicks;
previousPartialTicks = tickDelta;
}
// HEAD or RETURN
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V")
private void renderChunkLayer(RenderType renderType, PoseStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V")
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
{
// only render before solid blocks
if (renderType.equals(RenderType.solid()))
{
// get MC's current projection matrix
float[] mcProjMatrixRaw = new float[16];
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
// OpenGl outputs their matrices in col,row form instead of row,col
// (or maybe vice versa I have no idea :P)
mcProjectionMatrix.transpose();
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
}
@@ -1,6 +1,6 @@
package com.seibel.lod.fabric.mixins.events;
import com.seibel.lod.fabric.FabricMain;
import com.seibel.lod.fabric.Main;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
@@ -23,6 +23,6 @@ public abstract class MixinBlockUpdate {
@Inject(method = "handle(Lnet/minecraft/network/protocol/game/ClientGamePacketListener;)V", at = @At("TAIL"))
private void onBlockUpdate(ClientGamePacketListener clientGamePacketListener, CallbackInfo ci) {
FabricMain.client_proxy.blockChangeEvent(Minecraft.getInstance().player.clientLevel, this.getPos());
Main.client_proxy.blockChangeEvent(Minecraft.getInstance().player.clientLevel, this.getPos());
}
}
@@ -1,6 +1,6 @@
package com.seibel.lod.fabric.mixins.events;
import com.seibel.lod.fabric.FabricMain;
import com.seibel.lod.fabric.Main;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.renderer.LevelRenderer;
@@ -23,6 +23,6 @@ import java.util.function.Supplier;
public class MixinClientLevel {
@Inject(method = "<init>", at = @At("TAIL"))
private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, int i, Supplier<ProfilerFiller> supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
FabricMain.client_proxy.worldLoadEvent((ClientLevel) (Object) this);
Main.client_proxy.worldLoadEvent((ClientLevel) (Object) this);
}
}
@@ -1,10 +1,9 @@
package com.seibel.lod.fabric.mixins.events;
import com.seibel.lod.fabric.FabricMain;
import com.seibel.lod.fabric.Main;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
@@ -23,11 +22,11 @@ public class MixinMinecraft {
@Inject(method = "setLevel", at = @At("HEAD"))
private void unloadWorldEvent_sL(ClientLevel clientLevel, CallbackInfo ci) {
if (level != null) FabricMain.client_proxy.worldUnloadEvent(level);
if (level != null) Main.client_proxy.worldUnloadEvent(level);
}
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("HEAD"))
private void unloadWorldEvent_cL(Screen screen, CallbackInfo ci) {
if (this.level != null) FabricMain.client_proxy.worldUnloadEvent(this.level);
if (this.level != null) Main.client_proxy.worldUnloadEvent(this.level);
}
}
@@ -1,6 +1,6 @@
package com.seibel.lod.fabric.mixins.events;
import com.seibel.lod.fabric.FabricMain;
import com.seibel.lod.fabric.Main;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.ProgressListener;
import org.spongepowered.asm.mixin.Mixin;
@@ -14,8 +14,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
*/
@Mixin(ServerLevel.class)
public class MixinServerLevel {
@Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;save(Z)V", shift = At.Shift.AFTER))
private void saveWorldEvent(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
FabricMain.client_proxy.worldSaveEvent();
@Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;saveAll()V", shift = At.Shift.AFTER))
private void saveWorldEvent_sA(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
Main.client_proxy.worldSaveEvent();
}
@Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;autoSave()V", shift = At.Shift.AFTER))
private void saveWorldEvent_aS(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
Main.client_proxy.worldSaveEvent();
}
}
@@ -1,10 +1,8 @@
package com.seibel.lod.fabric.mixins.unsafe;
import net.minecraft.world.level.chunk.PalettedContainer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -19,13 +17,11 @@ import java.util.concurrent.Semaphore;
*/
@Mixin(PalettedContainer.class)
public class MixinPalettedContainer {
@Mutable
private Semaphore lock;
@Inject(method = "acquire", at = @At("HEAD"), cancellable = true)
private void acquire_skip(CallbackInfo ci) {
ci.cancel();
}
@Inject(method = "release", at = @At("HEAD"), cancellable = true)
private void release_skip(CallbackInfo ci) {
ci.cancel();
@Inject(method = "<init>", at = @At("RETURN"))
private void setSemaphore(CallbackInfo ci) {
this.lock = new Semaphore(2);
}
}
@@ -1,10 +1,7 @@
package com.seibel.lod.fabric.wrappers;
import com.seibel.lod.core.handlers.dependencyInjection.DependencyHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton;
/**
@@ -17,16 +14,10 @@ import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton;
* @author Ran
* @version 12-1-2021
*/
public class FabricDependencySetup
public class DependencySetup
{
public static void createInitialBindings()
{
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);;
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
}
public static void finishBinding()
{
SingletonHandler.finishBinding();
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
}
}
@@ -6,9 +6,6 @@ import com.terraformersmc.modmenu.api.ModMenuApi;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import java.util.HashMap;
import java.util.Map;
/**
* For making the config show up in modmenu
*/
@@ -1,3 +1,4 @@
package com.seibel.lod.fabric.wrappers.modAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
@@ -1,4 +1,3 @@
package com.seibel.lod.fabric.wrappers.modAccessor;
import java.util.HashSet;
@@ -22,4 +21,4 @@ public class OptifineAccessor implements IOptifineAccessor
return null;
}
}
}
@@ -3,65 +3,34 @@ package com.seibel.lod.fabric.wrappers.modAccessor;
import java.util.HashSet;
import java.util.stream.Collectors;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.level.LevelHeightAccessor;
public class SodiumAccessor implements ISodiumAccessor {
private final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
@Override
public String getModName() {
return "Sodium-Fabric-1.16.5";
}
return "Sodium-Fabric-1.17.1";
}
@Override
public HashSet<AbstractChunkPosWrapper> getNormalRenderedChunks() {
SodiumWorldRenderer renderer = SodiumWorldRenderer.getInstance();
LevelAccessor height = Minecraft.getInstance().level;
SodiumWorldRenderer renderer = SodiumWorldRenderer.instance();
LevelHeightAccessor height = Minecraft.getInstance().level;
// TODO: Maybe use a mixin to make this more efficient
return MC_RENDER.getMaximumRenderedChunks().stream().filter((AbstractChunkPosWrapper chunk) -> {
FakeChunkEntity AABB = new FakeChunkEntity(chunk.getX(), chunk.getZ(), height.getMaxBuildHeight());
return (renderer.isEntityVisible(AABB));
return (renderer.isBoxVisible(
chunk.getMinBlockX()+1, height.getMinBuildHeight()+1, chunk.getMinBlockZ()+1,
chunk.getMinBlockX()+15, height.getMaxBuildHeight()-1, chunk.getMinBlockZ()+15));
}).collect(Collectors.toCollection(HashSet::new));
}
private static class FakeChunkEntity extends Entity {
public int cx;
public int cz;
public int my;
public FakeChunkEntity(int chunkX, int chunkZ, int maxHeight) {
super(EntityType.AREA_EFFECT_CLOUD, null);
cx = chunkX;
cz = chunkZ;
my = maxHeight;
}
@Override
public AABB getBoundingBoxForCulling() {
return new AABB(cx*16+1, 1, cz*16+1,
cx*16+15, my-1, cz*16+15);
}
@Override
protected void defineSynchedData() {}
@Override
protected void readAdditionalSaveData(CompoundTag paramCompoundTag) {}
@Override
protected void addAdditionalSaveData(CompoundTag paramCompoundTag) {}
@Override
public Packet<?> getAddEntityPacket() {
throw new UnsupportedOperationException("This is a FAKE CHUNK ENTITY... For tricking the Sodium to check a AABB.");
}}
}
@@ -2,17 +2,17 @@
"required": true,
"minVersion": "0.8",
"package": "com.seibel.lod.fabric.mixins",
"compatibilityLevel": "JAVA_8",
"compatibilityLevel": "JAVA_16",
"mixins": [
"events.MixinServerLevel",
"unsafe.MixinPalettedContainer",
"MixinChunkGenerator"
"unsafe.MixinPalettedContainer"
],
"client": [
"MixinMinecraft",
"MixinOptionsScreen",
"MixinWorldRenderer",
"MixinFogRenderer",
"MixinChunkGenerator",
"events.MixinClientLevel",
"events.MixinMinecraft",
"events.MixinBlockUpdate"
+5 -5
View File
@@ -8,9 +8,9 @@
"authors": ["${authors}"],
"contact": {
"homepage": "${homepage}",
"sources": "${source}",
"issues": "${issues}"
"homepage": "https://www.curseforge.com/minecraft/mc-mods/distant-horizons",
"sources": "https://gitlab.com/jeseibel/minecraft-lod-mod/",
"issues": "https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues"
},
"license": "CC0-1.0",
@@ -34,8 +34,8 @@
"depends": {
"fabricloader": "*",
"fabric": "*",
"minecraft": ["1.16.5", "1.16.4", "1.16.3", "1.16.2"],
"java": ">=8"
"minecraft": "1.17.x",
"java": ">=16"
},
"suggests": {
"another-mod": "*"
+31 -10
View File
@@ -25,22 +25,16 @@ configurations {
developmentForge.extendsFrom common
}
def addMod(path, enabled) {
if (enabled == "2")
dependencies { modImplementation(path) }
else if (enabled == "1")
dependencies { modCompileOnly(path) }
}
dependencies {
// Forge loader
forge "net.minecraftforge:forge:${rootProject.minecraft_version}-${rootProject.forge_version}"
addMod("curse.maven:TerraForged-363820:${rootProject.terraforged_version}", rootProject.enable_terraforged)
common(project(path: ":common", configuration: "namedElements")) { transitive false }
shadowMe(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }
// Starlight
// modImplementation("curse.maven:starlight-forge-526854:${rootProject.starlight_version_forge}")
// forgeDependencies(project(":core")) { transitive false }
@@ -63,9 +57,36 @@ task copyCommonResources(type: Copy) {
into file("build/resources/main")
}
// Put stuff from gradle.properties into the mod info stuff
def resourceTargets = ["META-INF/mods.toml"]
def intoTargets = ["$buildDir/resources/main/"]
def replaceProperties = [
version: mod_version,
mod_name: mod_name,
authors: mod_authors,
description: mod_description
]
processResources {
dependsOn(copyCoreResources)
dependsOn(copyCommonResources)
inputs.properties replaceProperties
replaceProperties.put 'project', project
filesMatching(resourceTargets) {
expand replaceProperties
}
intoTargets.each { target ->
if (file(target).exists()) {
copy {
from(sourceSets.main.resources) {
include resourceTargets
expand replaceProperties
}
into target
}
}
}
}
shadowJar {
@@ -76,7 +97,7 @@ shadowJar {
configurations = [project.configurations.shadowMe]
relocate 'org.tukaani', 'shaded.tukaani'
relocate 'org.apache.commons.compress', 'shaded.apache.commons.compress'
relocate 'com.electronwill.nightconfig', 'shaded.electronwill.nightconfig'
relocate 'com.electronwill.nightconfig', 'shaded.electronwill.nightconfig' // This is already included with forge
relocate 'com.seibel.lod.common', 'forge.com.seibel.lod.common'
@@ -111,6 +111,4 @@ public class ForgeClientProxy
clientApi.keyPressedEvent(event.getKey());
}
}
@@ -22,13 +22,12 @@ package com.seibel.lod.forge;
import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.common.forge.LodForgeMethodCaller;
import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.api.ModAccessorApi;
import com.seibel.lod.core.handlers.ReflectionHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.lod.forge.wrappers.ForgeDependencySetup;
@@ -36,18 +35,19 @@ import com.seibel.lod.forge.wrappers.ForgeDependencySetup;
import com.seibel.lod.forge.wrappers.modAccessor.ModChecker;
import com.seibel.lod.forge.wrappers.modAccessor.OptifineAccessor;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fmlclient.ConfigGuiHandler;
import java.util.List;
import java.util.Random;
@@ -67,21 +67,16 @@ public class ForgeMain implements LodForgeMethodCaller
private void init(final FMLCommonSetupEvent event)
{
ApiShared.LOGGER.info("Distant Horizons initializing...");
// make sure the dependencies are set up before the mod needs them
LodCommonMain.initConfig();
LodCommonMain.startup(this, !FMLLoader.getDist().isClient());
// make sure the dependencies are set up before the mod needs them
ForgeDependencySetup.createInitialBindings();
ForgeDependencySetup.finishBinding();
// mod dependencies
ClientApi.LOGGER.info("Distant Horizons initializing...");
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
if (ReflectionHandler.instance.optifinePresent()) {
ModAccessorHandler.bind(IOptifineAccessor.class, new OptifineAccessor());
ModAccessorApi.bind(IOptifineAccessor.class, new OptifineAccessor());
}
ModAccessorHandler.finishBinding();
}
@@ -97,15 +92,21 @@ public class ForgeMain implements LodForgeMethodCaller
private void onClientStart(final FMLClientSetupEvent event)
{
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY,
() -> (client, parent) -> ConfigGui.getScreen(parent, ""));
ModLoadingContext.get().registerExtensionPoint(ConfigGuiHandler.ConfigGuiFactory.class,
() -> new ConfigGuiHandler.ConfigGuiFactory((client, parent) -> ConfigGui.getScreen(parent, "")));
forgeClientProxy = new ForgeClientProxy();
MinecraftForge.EVENT_BUS.register(forgeClientProxy);
}
private ModelDataMap dataMap = new ModelDataMap.Builder().build();
@Override
public List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random) {
public List<BakedQuad> getQuads(MinecraftWrapper mc, Block block, BlockState blockState, Direction direction, Random random) {
return mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
}
@Override
public int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) {
return sprite.getPixelRGBA(frameIndex, x, y);
}
}
@@ -6,8 +6,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.Camera;
@@ -20,32 +19,28 @@ import net.minecraft.world.level.material.FogType;
@Mixin(FogRenderer.class)
public class MixinFogRenderer {
// Using this instead of Float.MAX_VALUE because Sodium don't like it. (And keeping it for forge just in case)
private static final float A_REALLY_REALLY_BIG_VALUE = 4206942069.F;
private static final float A_EVEN_LARGER_VALUE = 420694206942069.F;
// Using this instead of Float.MAX_VALUE because Sodium don't like it. (And just in case it's here also for forge)
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("RETURN"),
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V")
private static final void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float ticks, CallbackInfo callback) {
ILodConfigWrapperSingleton CONFIG;
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V",
remap = false) // Due to this being a forge added method
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float tick, CallbackInfo callback) {
ILodConfigWrapperSingleton CONFIG;
try {
CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
} catch (NullPointerException e) {
return; // Can happen due to forge calling this before setting up the mod
return; // Happens on forge not loading the mod before this.
}
ApiShared.LOGGER.debug("LOD: MixinSetupFog called!");
FogType fogType = camera.getFluidInCamera();
FogType fogTypes = camera.getFluidInCamera();
Entity entity = camera.getEntity();
boolean isUnderWater = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
isUnderWater |= fogType.equals(FogType.WATER);
isUnderWater |= fogType.equals(FogType.LAVA);
if (!isUnderWater) {
if (fogMode == FogMode.FOG_TERRAIN && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
if (fogMode == FogMode.FOG_TERRAIN && fogTypes == FogType.NONE && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
}
}
}
}
}
@@ -3,7 +3,7 @@ package com.seibel.lod.forge.mixins;
import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.common.wrappers.config.TexturedButtonWidget;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.gui.screens.OptionsScreen;
import net.minecraft.client.gui.screens.Screen;
@@ -34,7 +34,7 @@ public class MixinOptionsScreen extends Screen {
@Inject(at = @At("HEAD"),method = "init")
private void lodconfig$init(CallbackInfo ci) {
if (SingletonHandler.get(ILodConfigWrapperSingleton.class).client().getOptionsButton())
this.addButton(new TexturedButtonWidget(
this.addRenderableWidget(new TexturedButtonWidget(
// Where the button is on the screen
this.width / 2 - 180, this.height / 6 - 12,
// Width and height of the button
@@ -1,49 +0,0 @@
package com.seibel.lod.forge.mixins;
import java.util.Random;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
//import com.seibel.lod.core.api.ClientApi;
import com.terraforged.mod.chunk.generator.FeatureGenerator;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
@Mixin(FeatureGenerator.class)
public class MixinTFChunkGenerator {
@Redirect(method = "decorate("
+ "Lnet/minecraft/world/level/StructureFeatureManager;"
+ "Lnet/minecraft/world/level/WorldGenLevel;"
+ "Lnet/minecraft/world/level/chunk/ChunkAccess;"
+ "Lnet/minecraft/world/level/biome/Biome;"
+ "Lnet/minecraft/core/BlockPos;"
+ "Lcom/terraforged/mod/profiler/watchdog/WatchdogContext;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/levelgen/feature/ConfiguredFeature;place("
+ "Lnet/minecraft/world/level/WorldGenLevel;"
+ "Lnet/minecraft/world/level/chunk/ChunkGenerator;"
+ "Ljava/util/Random;Lnet/minecraft/core/BlockPos;)Z"
))
private boolean wrapDecorate$FeaturePlace(ConfiguredFeature<?, ?> feature, WorldGenLevel arg,
ChunkGenerator arg2, Random random, BlockPos arg3) {
synchronized((FeatureGenerator)(Object)this) {
//ClientApi.LOGGER.info("wrapDecorate FeaturePlace triggered");
return feature.place(arg, arg2, random, arg3);
}
}
//METHOD: com.terraforged.mod.chunk.generator.FeatureGenerator.decorate(StructureFeatureManager manager,
// WorldGenLevel region, ChunkAccess chunk, Biome biome, BlockPos pos, WatchdogContext context)
//TARGET: boolean net.minecraft.world.level.levelgen.feature.ConfiguredFeature.place
// (WorldGenLevel arg, ChunkGenerator arg2, Random random, BlockPos arg3)
}
@@ -20,19 +20,17 @@
package com.seibel.lod.forge.mixins;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;
import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.client.renderer.LevelRenderer;
import org.lwjgl.opengl.GL15;
import net.minecraft.client.renderer.RenderType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.client.renderer.RenderType;
/**
* This class is used to mix in my rendering code
* before Minecraft starts rendering blocks.
@@ -49,35 +47,28 @@ import net.minecraft.client.renderer.RenderType;
@Mixin(LevelRenderer.class)
public class MixinWorldRenderer
{
// TODO: Fix clouds
private static float previousPartialTicks = 0;
public MixinWorldRenderer() {
throw new NullPointerException("Null cannot be cast to non-null type.");
}
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/vertex/PoseStack;F)V")
private void renderSky(PoseStack matrixStackIn, float partialTicks, CallbackInfo callback)
{
// get the partial ticks since renderBlockLayer doesn't
@Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true)
public void renderClouds(PoseStack poseStack, Matrix4f projectionMatrix, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) {
// get the partial ticks since renderChunkLayer doesn't
// have access to them
previousPartialTicks = partialTicks;
previousPartialTicks = tickDelta;
}
// HEAD or RETURN
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V")
private void renderChunkLayer(RenderType renderType, PoseStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V")
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
{
// only render before solid blocks
if (renderType.equals(RenderType.solid()))
{
// get MC's current projection matrix
float[] mcProjMatrixRaw = new float[16];
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
// OpenGl outputs their matrices in col,row form instead of row,col
// (or maybe vice versa I have no idea :P)
mcProjectionMatrix.transpose();
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
}
@@ -1,31 +1,23 @@
package com.seibel.lod.forge.wrappers;
import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.forge.wrappers.modAccessor.ModChecker;
/**
* Binds all necessary dependencies so we
* Binds all necessary dependencies, so we
* can access them in Core. <br>
* This needs to be called before any Core classes
* are loaded.
*
* @author James Seibel
* @author Ran
* @version 3-5-2022
* @version 12-1-2021
*/
public class ForgeDependencySetup
{
public static void createInitialBindings()
{
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
}
public static void finishBinding()
{
SingletonHandler.finishBinding();
}
}
@@ -10,4 +10,4 @@ public class ModChecker implements IModChecker {
public boolean isModLoaded(String modid) {
return ModList.get().isLoaded(modid);
}
}
}
@@ -1,4 +1,3 @@
package com.seibel.lod.forge.wrappers.modAccessor;
import java.util.HashSet;
@@ -22,4 +21,4 @@ public class OptifineAccessor implements IOptifineAccessor
return null;
}
}
}
+2 -2
View File
@@ -2,7 +2,7 @@
modLoader="javafml" #//mandatory
loaderVersion="[36,)" # // mandatory. This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
license="GNU GPLv3"
issueTrackerURL="${issues}"
issueTrackerURL="https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues"
[[mods]] #//mandatory
@@ -10,7 +10,7 @@ issueTrackerURL="${issues}"
version= "${version}" #//mandatory, gets the version number from jar populated by the build.gradle script
displayName="${mod_name}" #//mandatory
#//updateJSONURL="https://change.me.example.invalid/updates.json" # A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
displayURL="${homepage}"
displayURL="https://www.curseforge.com/minecraft/mc-mods/distant-horizons"
logoFile="logo.png"
catalogueImageIcon="icon.png"
credits="Massive thanks to: Leonardo, Cola, Ran, and CoolGi. For their hard work to bring Distant Horizons to where it is today. - James"
+3 -4
View File
@@ -2,10 +2,9 @@
"required": true,
"minVersion": "0.8",
"package": "com.seibel.lod.forge.mixins",
"compatibilityLevel": "JAVA_8",
"compatibilityLevel": "JAVA_16",
"mixins": [
"MixinChunkGenerator",
"MixinTFChunkGenerator"
"MixinChunkGenerator"
],
"client": [
"MixinOptionsScreen",
@@ -13,4 +12,4 @@
"MixinFogRenderer"
],
"server": []
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"pack": {
"description": "",
"pack_format": 6
"pack_format": 7
}
}
+14 -30
View File
@@ -1,9 +1,9 @@
org.gradle.jvmargs=-Xmx2048M
minecraft_version=1.16.5
minecraft_version=1.17.1
archives_base_name=DistantHorizons
mod_version=1.6.2a
mod_version=1.6.0a
maven_group=com.seibel.lod
toml_version=3.6.4
@@ -12,35 +12,19 @@ mod_name=Distant Horizons
mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow.
mod_authors=James Seibel, Leonardo Amato, Cola, coolGi2007, Ran, Leetom
mod_homepage=https://www.curseforge.com/minecraft/mc-mods/distant-horizons
mod_source=https://gitlab.com/jeseibel/minecraft-lod-mod/
mod_issues=https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues
# Fabric loader
fabric_loader_version=0.13.2
fabric_api_version=0.42.0+1.16
# Fabric mod versions
modmenu_version=1.16.22
lithium_version=mc1.16.5-0.6.6
sodium_version=3488820
iris_version=1.16.x-v1.1.4
# Fabric mod run
# 0 = Dont enable and dont run
# 1 = Can be refranced in code but dosnt run
# 2 = Can be refranced in code and runs in client
enable_lithium=0
enable_sodium=1
enable_iris=0
fabric_loader_version=0.12.6
fabric_api_version=0.37.1+1.17
# Fabric mods
modmenu_version=2.0.14
starlight_version_fabric=3442770
lithium_version=mc1.17.1-0.7.5
sodium_version=3605275
iris_version=1.17.x-v1.1.4
immersive_portals_version = 0.14-1.17
# Forge loader
forge_version=36.2.28
# Forge mod versions
terraforged_version=3285909
# Forge mod run
# 0 = Dont enable and dont run
# 1 = Can be refranced in code but dosnt run
# 2 = Can be refranced in code and runs in client
enable_terraforged=1
forge_version=37.1.1
# Forge mods
starlight_version_forge=3457784
Binary file not shown.