Compare commits
55 Commits
kotlin-1.1
...
0.9.8b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd4a4885fe | ||
|
|
9d59105af1 | ||
|
|
7cdddef1bf | ||
|
|
168fad883d | ||
|
|
572d517828 | ||
|
|
d4963ec173 | ||
|
|
ad83a511fb | ||
|
|
e351af2369 | ||
|
|
32a88fa824 | ||
|
|
ec723113d3 | ||
|
|
4e42f63c36 | ||
|
|
0daf61583a | ||
|
|
504f033c2e | ||
|
|
fa099b1b97 | ||
|
|
b0c0cd0d1b | ||
|
|
df69605521 | ||
|
|
d3b1d138ba | ||
|
|
07369159b8 | ||
|
|
6700e724a5 | ||
|
|
5b34da3e61 | ||
|
|
fc7c9a5381 | ||
|
|
cf7ae0efa1 | ||
|
|
04bb240d36 | ||
|
|
91fda1522c | ||
|
|
7ca25c0da7 | ||
|
|
0a05a67eda | ||
|
|
43e7fb830b | ||
|
|
c72e93aedf | ||
|
|
f236ef64ad | ||
|
|
d38f556bde | ||
|
|
fad662443d | ||
|
|
32c4dc6035 | ||
|
|
aee6e5caca | ||
|
|
5fbe2ff16f | ||
|
|
7a133c95a7 | ||
|
|
25b1d76c9e | ||
|
|
7a02179481 | ||
|
|
244907f4cd | ||
|
|
4ccd753c0c | ||
|
|
2715acf9c8 | ||
|
|
1c146fb070 | ||
|
|
44a20ceab3 | ||
|
|
1be2382fed | ||
|
|
e12b7b803c | ||
|
|
8a94867cd8 | ||
|
|
3a391f1677 | ||
|
|
d5dd1a36e3 | ||
|
|
a589c868a9 | ||
|
|
37ffa219fc | ||
|
|
220f2356d8 | ||
|
|
ec184f9916 | ||
|
|
2b1fd84cd5 | ||
|
|
30f199e9a2 | ||
|
|
0c66849175 | ||
|
|
3bd402b964 |
8
.classpath
Normal file
8
.classpath
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src/main/java"/>
|
||||||
|
<classpathentry kind="src" path="src/main/resources"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.springsource.ide.eclipse.gradle.classpathcontainer"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.gradle/
|
||||||
|
.settings/
|
||||||
|
bin/
|
||||||
|
build/
|
||||||
|
libs/
|
||||||
18
.project
Normal file
18
.project
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>BetterFoliage</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.springsource.ide.eclipse.gradle.core.nature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
BetterFoliage
|
BetterFoliage
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Minecraft mod that alters the appearance of leaves & grass
|
Minecraft mod that alters the appearance of leaves & grass
|
||||||
|
|
||||||
|
More info: http://www.minecraftforum.net/topic/2776217-better-foliage/
|
||||||
|
|
||||||
|
Download
|
||||||
|
========
|
||||||
|
[BetterFoliage 0.9.7-beta] (http://goo.gl/xNVloR) (MC 1.7.2 & 1.7.10)
|
||||||
|
|||||||
45
build.gradle
Normal file
45
build.gradle
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
name = "forge"
|
||||||
|
url = "http://files.minecraftforge.net/maven"
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
name = "sonatype"
|
||||||
|
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apply plugin: 'forge'
|
||||||
|
|
||||||
|
minecraft {
|
||||||
|
version = '1.7.2-10.12.2.1147'
|
||||||
|
}
|
||||||
|
|
||||||
|
jar.baseName = 'BetterFoliage'
|
||||||
|
group = 'com.github.octarine-noise'
|
||||||
|
version='0.9.8b'
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
inputs.property "version", project.version
|
||||||
|
inputs.property "mcversion", project.minecraft.version
|
||||||
|
|
||||||
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
|
include 'mcmod.info'
|
||||||
|
expand 'version':project.version, 'mcversion':project.minecraft.version
|
||||||
|
}
|
||||||
|
|
||||||
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
|
exclude 'mcmod.info'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
manifest {
|
||||||
|
attributes("FMLCorePlugin": "mods.betterfoliage.loader.BetterFoliageLoader", "FMLCorePluginContainsFMLMod": "mods.betterfoliage.BetterFoliage")
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/main/java/mods/betterfoliage/BetterFoliage.java
Normal file
48
src/main/java/mods/betterfoliage/BetterFoliage.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package mods.betterfoliage;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import mods.betterfoliage.client.BetterFoliageClient;
|
||||||
|
import mods.betterfoliage.common.config.BetterFoliageConfig;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.Mod;
|
||||||
|
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||||
|
import cpw.mods.fml.common.network.NetworkCheckHandler;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
|
||||||
|
@Mod(name=BetterFoliage.MOD_NAME, modid=BetterFoliage.MOD_ID, acceptedMinecraftVersions=BetterFoliage.MC_VERSIONS, guiFactory=BetterFoliage.GUI_FACTORY)
|
||||||
|
public class BetterFoliage {
|
||||||
|
|
||||||
|
public static final String MOD_ID = "BetterFoliage";
|
||||||
|
public static final String MOD_NAME = "Better Foliage";
|
||||||
|
public static final String MC_VERSIONS = "[1.7.2,1.7.10]";
|
||||||
|
public static final String GUI_FACTORY = "mods.betterfoliage.client.gui.ConfigGuiFactory";
|
||||||
|
|
||||||
|
@Mod.Instance
|
||||||
|
public static BetterFoliage instance;
|
||||||
|
|
||||||
|
public static BetterFoliageConfig config = new BetterFoliageConfig();
|
||||||
|
|
||||||
|
public static Logger log;
|
||||||
|
|
||||||
|
public static File configDir;
|
||||||
|
|
||||||
|
@Mod.EventHandler
|
||||||
|
public void preInit(FMLPreInitializationEvent event) {
|
||||||
|
log = event.getModLog();
|
||||||
|
if (event.getSide() == Side.CLIENT) {
|
||||||
|
configDir = new File(event.getModConfigurationDirectory(), MOD_ID);
|
||||||
|
configDir.mkdir();
|
||||||
|
config.load(new File(configDir, "betterfoliage.cfg"));
|
||||||
|
BetterFoliageClient.preInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NetworkCheckHandler
|
||||||
|
public boolean checkVersion(Map<String, String> mods, Side side) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
117
src/main/java/mods/betterfoliage/client/BetterFoliageClient.java
Normal file
117
src/main/java/mods/betterfoliage/client/BetterFoliageClient.java
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
package mods.betterfoliage.client;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
||||||
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterAlgae;
|
||||||
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterCactus;
|
||||||
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterCoral;
|
||||||
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterGrass;
|
||||||
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterLeaves;
|
||||||
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterLilypad;
|
||||||
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterReed;
|
||||||
|
import mods.betterfoliage.client.resource.BlockTextureGenerator;
|
||||||
|
import mods.betterfoliage.client.resource.HalfTextureResource;
|
||||||
|
import mods.betterfoliage.client.resource.LeafTextureGenerator;
|
||||||
|
import mods.betterfoliage.client.resource.ShortGrassTextureResource;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.client.resources.IResource;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||||
|
import cpw.mods.fml.common.FMLCommonHandler;
|
||||||
|
|
||||||
|
public class BetterFoliageClient {
|
||||||
|
|
||||||
|
public static Map<Integer, IRenderBlockDecorator> decorators = Maps.newHashMap();
|
||||||
|
public static LeafTextureGenerator leafGenerator;
|
||||||
|
|
||||||
|
public static BlockMatcher leaves = new BlockMatcher();
|
||||||
|
public static BlockMatcher crops = new BlockMatcher();
|
||||||
|
|
||||||
|
public static void preInit() {
|
||||||
|
FMLCommonHandler.instance().bus().register(new KeyHandler());
|
||||||
|
|
||||||
|
BetterFoliage.log.info("Registering renderers");
|
||||||
|
registerRenderer(new RenderBlockBetterLeaves());
|
||||||
|
registerRenderer(new RenderBlockBetterGrass());
|
||||||
|
registerRenderer(new RenderBlockBetterCactus());
|
||||||
|
registerRenderer(new RenderBlockBetterLilypad());
|
||||||
|
registerRenderer(new RenderBlockBetterReed());
|
||||||
|
registerRenderer(new RenderBlockBetterAlgae());
|
||||||
|
registerRenderer(new RenderBlockBetterCoral());
|
||||||
|
|
||||||
|
leaves.load(new File(BetterFoliage.configDir, "classesLeaves.cfg"), new ResourceLocation("betterfoliage:classesLeavesDefault.cfg"));
|
||||||
|
MinecraftForge.EVENT_BUS.register(leaves);
|
||||||
|
|
||||||
|
crops.load(new File(BetterFoliage.configDir, "classesCrops.cfg"), new ResourceLocation("betterfoliage:classesCropsDefault.cfg"));
|
||||||
|
MinecraftForge.EVENT_BUS.register(crops);
|
||||||
|
|
||||||
|
BetterFoliage.log.info("Registering leaf texture generator");
|
||||||
|
leafGenerator = new LeafTextureGenerator();
|
||||||
|
MinecraftForge.EVENT_BUS.register(leafGenerator);
|
||||||
|
|
||||||
|
MinecraftForge.EVENT_BUS.register(new BlockTextureGenerator("bf_reed_bottom", new ResourceLocation("betterfoliage", "textures/blocks/missing_leaf.png")) {
|
||||||
|
@Override
|
||||||
|
public IResource getResource(ResourceLocation var1) throws IOException {
|
||||||
|
return new HalfTextureResource(unwrapResource(var1), true, getMissingResource());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
MinecraftForge.EVENT_BUS.register(new BlockTextureGenerator("bf_reed_top", new ResourceLocation("betterfoliage", "textures/blocks/missing_leaf.png")) {
|
||||||
|
@Override
|
||||||
|
public IResource getResource(ResourceLocation var1) throws IOException {
|
||||||
|
return new HalfTextureResource(unwrapResource(var1), false, getMissingResource());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
MinecraftForge.EVENT_BUS.register(new BlockTextureGenerator("bf_shortgrass", new ResourceLocation("betterfoliage", "textures/blocks/missing_leaf.png")) {
|
||||||
|
@Override
|
||||||
|
public IResource getResource(ResourceLocation var1) throws IOException {
|
||||||
|
return new ShortGrassTextureResource(unwrapResource(var1), false, getMissingResource());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
MinecraftForge.EVENT_BUS.register(new BlockTextureGenerator("bf_shortgrass_snow", new ResourceLocation("betterfoliage", "textures/blocks/missing_leaf.png")) {
|
||||||
|
@Override
|
||||||
|
public IResource getResource(ResourceLocation var1) throws IOException {
|
||||||
|
return new ShortGrassTextureResource(unwrapResource(var1), true, getMissingResource());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
MinecraftForge.EVENT_BUS.register(new BetterFoliageClient());
|
||||||
|
|
||||||
|
ShadersModIntegration.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isLeafTexture(TextureAtlasSprite icon) {
|
||||||
|
String resourceLocation = icon.getIconName();
|
||||||
|
if (resourceLocation.startsWith("forestry:leaves/")) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getRenderTypeOverride(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
|
||||||
|
// universal sign for DON'T RENDER ME!
|
||||||
|
if (original == -1) return original;
|
||||||
|
|
||||||
|
for (Map.Entry<Integer, IRenderBlockDecorator> entry : decorators.entrySet())
|
||||||
|
if (entry.getValue().isBlockAccepted(blockAccess, x, y, z, block, original))
|
||||||
|
return entry.getKey();
|
||||||
|
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerRenderer(IRenderBlockDecorator decorator) {
|
||||||
|
int renderId = RenderingRegistry.getNextAvailableRenderId();
|
||||||
|
decorators.put(renderId, decorator);
|
||||||
|
RenderingRegistry.registerBlockHandler(renderId, decorator);
|
||||||
|
MinecraftForge.EVENT_BUS.register(decorator);
|
||||||
|
decorator.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
83
src/main/java/mods/betterfoliage/client/BlockMatcher.java
Normal file
83
src/main/java/mods/betterfoliage/client/BlockMatcher.java
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package mods.betterfoliage.client;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.common.util.Utils;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.client.multiplayer.WorldClient;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
|
||||||
|
public class BlockMatcher {
|
||||||
|
|
||||||
|
public Set<Class<?>> whiteList = Sets.newHashSet();
|
||||||
|
public Set<Class<?>> blackList = Sets.newHashSet();
|
||||||
|
public Set<Integer> blockIDs = Sets.newHashSet();
|
||||||
|
|
||||||
|
public void addClass(String className) {
|
||||||
|
try {
|
||||||
|
if (className.startsWith("-"))
|
||||||
|
blackList.add(Class.forName(className.substring(1)));
|
||||||
|
else
|
||||||
|
whiteList.add(Class.forName(className));
|
||||||
|
} catch(ClassNotFoundException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matchesClass(Block block) {
|
||||||
|
for (Class<?> clazz : blackList) if (clazz.isAssignableFrom(block.getClass())) return false;
|
||||||
|
for (Class<?> clazz : whiteList) if (clazz.isAssignableFrom(block.getClass())) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matchesID(int blockId) {
|
||||||
|
return blockIDs.contains(blockId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matchesID(Block block) {
|
||||||
|
return blockIDs.contains(Block.blockRegistry.getIDForObject(block));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(File file, ResourceLocation defaults) {
|
||||||
|
if (!file.exists()) Utils.copyFromTextResource(defaults, file);
|
||||||
|
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try {
|
||||||
|
reader = new BufferedReader(new FileReader(file));
|
||||||
|
whiteList.clear();
|
||||||
|
blackList.clear();
|
||||||
|
String line = reader.readLine();
|
||||||
|
while(line != null) {
|
||||||
|
addClass(line.trim());
|
||||||
|
line = reader.readLine();
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
BetterFoliage.log.warn(String.format("Error reading configuration: %s", file.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Caches block IDs on world load for fast lookup
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleWorldLoad(WorldEvent.Load event) {
|
||||||
|
if (!(event.world instanceof WorldClient)) return;
|
||||||
|
|
||||||
|
blockIDs.clear();
|
||||||
|
Iterator<Block> iter = Block.blockRegistry.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Block block = iter.next();
|
||||||
|
if (matchesClass(block)) blockIDs.add(Block.blockRegistry.getIDForObject(block));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/main/java/mods/betterfoliage/client/KeyHandler.java
Normal file
27
src/main/java/mods/betterfoliage/client/KeyHandler.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package mods.betterfoliage.client;
|
||||||
|
|
||||||
|
import cpw.mods.fml.client.FMLClientHandler;
|
||||||
|
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.common.gameevent.InputEvent;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.gui.ConfigGuiMain;
|
||||||
|
import net.minecraft.client.settings.KeyBinding;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class KeyHandler {
|
||||||
|
|
||||||
|
public static KeyBinding guiBinding;
|
||||||
|
|
||||||
|
public KeyHandler() {
|
||||||
|
guiBinding = new KeyBinding("key.betterfoliage.gui", 66, BetterFoliage.MOD_NAME);
|
||||||
|
ClientRegistry.registerKeyBinding(guiBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleKeyPress(InputEvent.KeyInputEvent event) {
|
||||||
|
if (guiBinding.isPressed()) FMLClientHandler.instance().showGuiScreen(new ConfigGuiMain(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package mods.betterfoliage.client;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
|
||||||
|
public class ShadersModIntegration {
|
||||||
|
|
||||||
|
private static boolean hasShadersMod = false;
|
||||||
|
private static int tallGrassEntityData;
|
||||||
|
private static int leavesEntityData;
|
||||||
|
private static Field shadersEntityData;
|
||||||
|
private static Field shadersEntityDataIndex;
|
||||||
|
|
||||||
|
private ShadersModIntegration() {}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
tallGrassEntityData = Block.blockRegistry.getIDForObject(Blocks.tallgrass) & 0xFFFF | Blocks.tallgrass.getRenderType() << 16;
|
||||||
|
leavesEntityData = Block.blockRegistry.getIDForObject(Blocks.leaves) & 0xFFFF | Blocks.leaves.getRenderType() << 16;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> classShaders = Class.forName("shadersmodcore.client.Shaders");
|
||||||
|
shadersEntityData = classShaders.getDeclaredField("entityData");
|
||||||
|
shadersEntityDataIndex = classShaders.getDeclaredField("entityDataIndex");
|
||||||
|
hasShadersMod = true;
|
||||||
|
} catch(Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startGrassQuads() {
|
||||||
|
if (!hasShadersMod) return;
|
||||||
|
setShadersEntityData(tallGrassEntityData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startLeavesQuads() {
|
||||||
|
if (!hasShadersMod) return;
|
||||||
|
setShadersEntityData(leavesEntityData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setShadersEntityData(int data) {
|
||||||
|
try {
|
||||||
|
int[] entityData = (int[]) shadersEntityData.get(null);
|
||||||
|
int entityDataIndex = shadersEntityDataIndex.getInt(null);
|
||||||
|
entityData[(entityDataIndex * 2)] = data;
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getBlockIdOverride(int original, Block block) {
|
||||||
|
if (BetterFoliageClient.leaves.matchesID(original & 0xFFFF)) return leavesEntityData;
|
||||||
|
if (BetterFoliageClient.crops.matchesID(original & 0xFFFF)) return tallGrassEntityData;
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package mods.betterfoliage.client.gui;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionDoubleWidget;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionIntegerWidget;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import cpw.mods.fml.client.FMLClientHandler;
|
||||||
|
|
||||||
|
public class ConfigGuiAlgae extends ConfigGuiScreenBase {
|
||||||
|
|
||||||
|
public ConfigGuiAlgae(GuiScreen parent) {
|
||||||
|
super(parent);
|
||||||
|
int id = 10;
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.algaeHOffset, -100, -70, 200, 50, id++, id++, "message.betterfoliage.hOffset", "%.3f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.algaeSize, -100, -40, 200, 50, id++, id++, "message.betterfoliage.size", "%.2f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.algaeHeightMin, -100, -10, 200, 50, id++, id++, "message.betterfoliage.minHeight", "%.2f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.algaeHeightMax, -100, 20, 200, 50, id++, id++, "message.betterfoliage.maxHeight", "%.2f"));
|
||||||
|
widgets.add(new OptionIntegerWidget(BetterFoliage.config.algaeChance, -100, 50, 200, 50, id++, id++, "message.betterfoliage.algaeChance"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void addButtons(int x, int y) {
|
||||||
|
buttonList.add(new GuiButton(0, x - 50, y + 100, 100, 20, I18n.format("message.betterfoliage.back")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onButtonPress(int id) {
|
||||||
|
if (id == 0) FMLClientHandler.instance().showGuiScreen(parent);
|
||||||
|
|
||||||
|
if (BetterFoliage.config.algaeHeightMin.value > BetterFoliage.config.algaeHeightMax.value) BetterFoliage.config.algaeHeightMin.value = BetterFoliage.config.algaeHeightMax.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package mods.betterfoliage.client.gui;
|
||||||
|
|
||||||
|
import cpw.mods.fml.client.FMLClientHandler;
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionDoubleWidget;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionIntegerWidget;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
|
||||||
|
public class ConfigGuiCoral extends ConfigGuiScreenBase {
|
||||||
|
|
||||||
|
public ConfigGuiCoral(GuiScreen parent) {
|
||||||
|
super(parent);
|
||||||
|
int id = 10;
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.coralCrustSize, -100, -100, 200, 50, id++, id++, "message.betterfoliage.crustSize", "%.2f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.coralVOffset, -100, -70, 200, 50, id++, id++, "message.betterfoliage.vOffset", "%.3f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.coralSize, -100, -40, 200, 50, id++, id++, "message.betterfoliage.size", "%.2f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.coralHOffset, -100, -10, 200, 50, id++, id++, "message.betterfoliage.hOffset", "%.3f"));
|
||||||
|
widgets.add(new OptionIntegerWidget(BetterFoliage.config.coralPopulation, -100, 20, 200, 50, id++, id++, "message.betterfoliage.coralPopulation"));
|
||||||
|
widgets.add(new OptionIntegerWidget(BetterFoliage.config.coralChance, -100, 50, 200, 50, id++, id++, "message.betterfoliage.coralChance"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void addButtons(int x, int y) {
|
||||||
|
buttonList.add(new GuiButton(0, x - 50, y + 80, 100, 20, I18n.format("message.betterfoliage.back")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onButtonPress(int id) {
|
||||||
|
if (id == 0) FMLClientHandler.instance().showGuiScreen(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package mods.betterfoliage.client.gui;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import cpw.mods.fml.client.IModGuiFactory;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class ConfigGuiFactory implements IModGuiFactory {
|
||||||
|
|
||||||
|
public void initialize(Minecraft minecraftInstance) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<? extends GuiScreen> mainConfigGuiClass() {
|
||||||
|
return ConfigGuiMain.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() {
|
||||||
|
return ImmutableSet.<RuntimeOptionCategoryElement>of();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package mods.betterfoliage.client.gui;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionDoubleWidget;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import cpw.mods.fml.client.FMLClientHandler;
|
||||||
|
|
||||||
|
public class ConfigGuiGrass extends ConfigGuiScreenBase {
|
||||||
|
|
||||||
|
public enum Button {CLOSE, GRASS_USE_GENERATED}
|
||||||
|
|
||||||
|
public ConfigGuiGrass(GuiScreen parent) {
|
||||||
|
super(parent);
|
||||||
|
int id = 10;
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.grassSize, -100, -70, 200, 50, id++, id++, "message.betterfoliage.size", "%.2f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.grassHOffset, -100, -10, 200, 50, id++, id++, "message.betterfoliage.hOffset", "%.3f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.grassHeightMin, -100, 20, 200, 50, id++, id++, "message.betterfoliage.minHeight", "%.2f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.grassHeightMax, -100, 50, 200, 50, id++, id++, "message.betterfoliage.maxHeight", "%.2f"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void addButtons(int x, int y) {
|
||||||
|
buttonList.add(new GuiButton(Button.CLOSE.ordinal(), x - 50, y + 80, 100, 20, I18n.format("message.betterfoliage.back")));
|
||||||
|
buttonList.add(new GuiButton(Button.GRASS_USE_GENERATED.ordinal(), x - 100, y - 40, 200, 20, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateButtons() {
|
||||||
|
setButtonOptionBoolean(Button.GRASS_USE_GENERATED.ordinal(), "message.betterfoliage.genShortgrass", BetterFoliage.config.grassUseGenerated);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onButtonPress(int id) {
|
||||||
|
if (id == Button.CLOSE.ordinal()) FMLClientHandler.instance().showGuiScreen(parent);
|
||||||
|
if (id == Button.GRASS_USE_GENERATED.ordinal()) BetterFoliage.config.grassUseGenerated = !BetterFoliage.config.grassUseGenerated;
|
||||||
|
|
||||||
|
if (BetterFoliage.config.grassHeightMin.value > BetterFoliage.config.grassHeightMax.value) BetterFoliage.config.grassHeightMin.value = BetterFoliage.config.grassHeightMax.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package mods.betterfoliage.client.gui;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionDoubleWidget;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import cpw.mods.fml.client.FMLClientHandler;
|
||||||
|
|
||||||
|
public class ConfigGuiLeaves extends ConfigGuiScreenBase {
|
||||||
|
|
||||||
|
public enum Button {CLOSE, LEAVES_OFFSET_MODE}
|
||||||
|
|
||||||
|
public ConfigGuiLeaves(GuiScreen parent) {
|
||||||
|
super(parent);
|
||||||
|
int id = 10;
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.leavesSize, -100, -70, 200, 50, id++, id++, "message.betterfoliage.size", "%.2f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.leavesHOffset, -100, -10, 200, 50, id++, id++, "message.betterfoliage.hOffset", "%.3f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.leavesVOffset, -100, 20, 200, 50, id++, id++, "message.betterfoliage.vOffset", "%.3f"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void addButtons(int x, int y) {
|
||||||
|
buttonList.add(new GuiButton(Button.CLOSE.ordinal(), x - 50, y + 50, 100, 20, I18n.format("message.betterfoliage.back")));
|
||||||
|
buttonList.add(new GuiButton(Button.LEAVES_OFFSET_MODE.ordinal(), x - 100, y - 40, 200, 20, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateButtons() {
|
||||||
|
setButtonOptionBoolean(Button.LEAVES_OFFSET_MODE.ordinal(), "message.betterfoliage.leavesMode", BetterFoliage.config.leavesSkew ? "message.betterfoliage.leavesSkew" : "message.betterfoliage.leavesTranslate");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onButtonPress(int id) {
|
||||||
|
if (id == Button.CLOSE.ordinal()) FMLClientHandler.instance().showGuiScreen(parent);
|
||||||
|
if (id == Button.LEAVES_OFFSET_MODE.ordinal()) BetterFoliage.config.leavesSkew = !BetterFoliage.config.leavesSkew;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package mods.betterfoliage.client.gui;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionDoubleWidget;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionIntegerWidget;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import cpw.mods.fml.client.FMLClientHandler;
|
||||||
|
|
||||||
|
public class ConfigGuiLilypad extends ConfigGuiScreenBase {
|
||||||
|
|
||||||
|
public ConfigGuiLilypad(GuiScreen parent) {
|
||||||
|
super(parent);
|
||||||
|
int id = 10;
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.lilypadHOffset, -100, -40, 200, 50, id++, id++, "message.betterfoliage.hOffset", "%.3f"));
|
||||||
|
widgets.add(new OptionIntegerWidget(BetterFoliage.config.lilypadChance, -100, -10, 200, 50, id++, id++, "message.betterfoliage.flowerChance"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void addButtons(int x, int y) {
|
||||||
|
buttonList.add(new GuiButton(0, x - 50, y + 50, 100, 20, I18n.format("message.betterfoliage.back")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onButtonPress(int id) {
|
||||||
|
if (id == 0) FMLClientHandler.instance().showGuiScreen(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package mods.betterfoliage.client.gui;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import cpw.mods.fml.client.FMLClientHandler;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class ConfigGuiMain extends ConfigGuiScreenBase {
|
||||||
|
|
||||||
|
public enum Button {CLOSE,
|
||||||
|
TOGGLE_LEAVES, CONFIG_LEAVES,
|
||||||
|
TOGGLE_GRASS, CONFIG_GRASS,
|
||||||
|
TOGGLE_CACTUS, CONFIG_CACTUS,
|
||||||
|
TOGGLE_LILYPAD, CONFIG_LILYPAD,
|
||||||
|
TOGGLE_REED, CONFIG_REED,
|
||||||
|
TOGGLE_ALGAE, CONFIG_ALGAE,
|
||||||
|
TOGGLE_CORAL, CONFIG_CORAL}
|
||||||
|
|
||||||
|
public ConfigGuiMain(GuiScreen parent) {
|
||||||
|
super(parent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected void addButtons(int x, int y) {
|
||||||
|
buttonList.add(new GuiButton(Button.CLOSE.ordinal(), x - 50, y + 110, 100, 20, I18n.format("message.betterfoliage.close")));
|
||||||
|
|
||||||
|
buttonList.add(new GuiButton(Button.TOGGLE_LEAVES.ordinal(), x - 100, y - 100, 150, 20, ""));
|
||||||
|
buttonList.add(new GuiButton(Button.CONFIG_LEAVES.ordinal(), x + 60, y - 100, 40, 20, I18n.format("message.betterfoliage.config")));
|
||||||
|
|
||||||
|
buttonList.add(new GuiButton(Button.TOGGLE_GRASS.ordinal(), x - 100, y - 70, 150, 20, ""));
|
||||||
|
buttonList.add(new GuiButton(Button.CONFIG_GRASS.ordinal(), x + 60, y - 70, 40, 20, I18n.format("message.betterfoliage.config")));
|
||||||
|
|
||||||
|
buttonList.add(new GuiButton(Button.TOGGLE_CACTUS.ordinal(), x - 100, y - 40, 150, 20, ""));
|
||||||
|
buttonList.add(new GuiButton(Button.CONFIG_CACTUS.ordinal(), x + 60, y - 40, 40, 20, I18n.format("message.betterfoliage.config")));
|
||||||
|
|
||||||
|
buttonList.add(new GuiButton(Button.TOGGLE_LILYPAD.ordinal(), x - 100, y - 10, 150, 20, ""));
|
||||||
|
buttonList.add(new GuiButton(Button.CONFIG_LILYPAD.ordinal(), x + 60, y - 10, 40, 20, I18n.format("message.betterfoliage.config")));
|
||||||
|
|
||||||
|
buttonList.add(new GuiButton(Button.TOGGLE_REED.ordinal(), x - 100, y + 20, 150, 20, ""));
|
||||||
|
buttonList.add(new GuiButton(Button.CONFIG_REED.ordinal(), x + 60, y + 20, 40, 20, I18n.format("message.betterfoliage.config")));
|
||||||
|
|
||||||
|
buttonList.add(new GuiButton(Button.TOGGLE_ALGAE.ordinal(), x - 100, y + 50, 150, 20, ""));
|
||||||
|
buttonList.add(new GuiButton(Button.CONFIG_ALGAE.ordinal(), x + 60, y + 50, 40, 20, I18n.format("message.betterfoliage.config")));
|
||||||
|
|
||||||
|
buttonList.add(new GuiButton(Button.TOGGLE_CORAL.ordinal(), x - 100, y + 80, 150, 20, ""));
|
||||||
|
buttonList.add(new GuiButton(Button.CONFIG_CORAL.ordinal(), x + 60, y + 80, 40, 20, I18n.format("message.betterfoliage.config")));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateButtons() {
|
||||||
|
setButtonOptionBoolean(Button.TOGGLE_LEAVES.ordinal(), "message.betterfoliage.betterLeaves", BetterFoliage.config.leavesEnabled);
|
||||||
|
setButtonOptionBoolean(Button.TOGGLE_GRASS.ordinal(), "message.betterfoliage.betterGrass", BetterFoliage.config.grassEnabled);
|
||||||
|
setButtonOptionBoolean(Button.TOGGLE_CACTUS.ordinal(), "message.betterfoliage.betterCactus", BetterFoliage.config.cactusEnabled);
|
||||||
|
setButtonOptionBoolean(Button.TOGGLE_LILYPAD.ordinal(), "message.betterfoliage.betterLilypad", BetterFoliage.config.lilypadEnabled);
|
||||||
|
setButtonOptionBoolean(Button.TOGGLE_REED.ordinal(), "message.betterfoliage.betterReed", BetterFoliage.config.reedEnabled);
|
||||||
|
setButtonOptionBoolean(Button.TOGGLE_ALGAE.ordinal(), "message.betterfoliage.betterAlgae", BetterFoliage.config.algaeEnabled);
|
||||||
|
setButtonOptionBoolean(Button.TOGGLE_CORAL.ordinal(), "message.betterfoliage.betterCoral", BetterFoliage.config.coralEnabled);
|
||||||
|
((GuiButton) buttonList.get(Button.CONFIG_CACTUS.ordinal())).enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onButtonPress(int id) {
|
||||||
|
if (id == Button.CLOSE.ordinal()) {
|
||||||
|
BetterFoliage.config.save();
|
||||||
|
Minecraft.getMinecraft().renderGlobal.loadRenderers();
|
||||||
|
FMLClientHandler.instance().showGuiScreen(parent);
|
||||||
|
}
|
||||||
|
if (id == Button.TOGGLE_LEAVES.ordinal()) BetterFoliage.config.leavesEnabled = !BetterFoliage.config.leavesEnabled;
|
||||||
|
if (id == Button.TOGGLE_GRASS.ordinal()) BetterFoliage.config.grassEnabled = !BetterFoliage.config.grassEnabled;
|
||||||
|
if (id == Button.TOGGLE_CACTUS.ordinal()) BetterFoliage.config.cactusEnabled = !BetterFoliage.config.cactusEnabled;
|
||||||
|
if (id == Button.TOGGLE_LILYPAD.ordinal()) BetterFoliage.config.lilypadEnabled = !BetterFoliage.config.lilypadEnabled;
|
||||||
|
if (id == Button.TOGGLE_REED.ordinal()) BetterFoliage.config.reedEnabled = !BetterFoliage.config.reedEnabled;
|
||||||
|
if (id == Button.TOGGLE_ALGAE.ordinal()) BetterFoliage.config.algaeEnabled = !BetterFoliage.config.algaeEnabled;
|
||||||
|
if (id == Button.TOGGLE_CORAL.ordinal()) BetterFoliage.config.coralEnabled = !BetterFoliage.config.coralEnabled;
|
||||||
|
|
||||||
|
if (id== Button.CONFIG_LEAVES.ordinal()) FMLClientHandler.instance().showGuiScreen(new ConfigGuiLeaves(this));
|
||||||
|
if (id== Button.CONFIG_GRASS.ordinal()) FMLClientHandler.instance().showGuiScreen(new ConfigGuiGrass(this));
|
||||||
|
if (id== Button.CONFIG_LILYPAD.ordinal()) FMLClientHandler.instance().showGuiScreen(new ConfigGuiLilypad(this));
|
||||||
|
if (id== Button.CONFIG_REED.ordinal()) FMLClientHandler.instance().showGuiScreen(new ConfigGuiReed(this));
|
||||||
|
if (id== Button.CONFIG_ALGAE.ordinal()) FMLClientHandler.instance().showGuiScreen(new ConfigGuiAlgae(this));
|
||||||
|
if (id== Button.CONFIG_CORAL.ordinal()) FMLClientHandler.instance().showGuiScreen(new ConfigGuiCoral(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package mods.betterfoliage.client.gui;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionDoubleWidget;
|
||||||
|
import mods.betterfoliage.client.gui.widget.OptionIntegerWidget;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import cpw.mods.fml.client.FMLClientHandler;
|
||||||
|
|
||||||
|
public class ConfigGuiReed extends ConfigGuiScreenBase {
|
||||||
|
|
||||||
|
public ConfigGuiReed(GuiScreen parent) {
|
||||||
|
super(parent);
|
||||||
|
int id = 10;
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.reedHOffset, -100, -70, 200, 50, id++, id++, "message.betterfoliage.hOffset", "%.3f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.reedHeightMin, -100, -40, 200, 50, id++, id++, "message.betterfoliage.minHeight", "%.2f"));
|
||||||
|
widgets.add(new OptionDoubleWidget(BetterFoliage.config.reedHeightMax, -100, -10, 200, 50, id++, id++, "message.betterfoliage.maxHeight", "%.2f"));
|
||||||
|
widgets.add(new OptionIntegerWidget(BetterFoliage.config.reedChance, -100, 20, 200, 50, id++, id++, "message.betterfoliage.reedChance"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void addButtons(int x, int y) {
|
||||||
|
buttonList.add(new GuiButton(0, x - 50, y + 50, 100, 20, I18n.format("message.betterfoliage.back")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onButtonPress(int id) {
|
||||||
|
if (id == 0) FMLClientHandler.instance().showGuiScreen(parent);
|
||||||
|
|
||||||
|
if (BetterFoliage.config.reedHeightMin.value > BetterFoliage.config.reedHeightMax.value) BetterFoliage.config.reedHeightMin.value = BetterFoliage.config.reedHeightMax.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package mods.betterfoliage.client.gui;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import mods.betterfoliage.client.gui.widget.IOptionWidget;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import net.minecraft.util.EnumChatFormatting;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
public class ConfigGuiScreenBase extends GuiScreen {
|
||||||
|
|
||||||
|
protected GuiScreen parent;
|
||||||
|
protected List<IOptionWidget> widgets = Lists.newLinkedList();
|
||||||
|
|
||||||
|
public ConfigGuiScreenBase(GuiScreen parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawScreen(int par1, int par2, float par3) {
|
||||||
|
this.drawDefaultBackground();
|
||||||
|
int x = width / 2;
|
||||||
|
int y = height / 2;
|
||||||
|
for (IOptionWidget widget : widgets) widget.drawStrings(this, fontRendererObj, x, y, 14737632, 16777120);
|
||||||
|
super.drawScreen(par1, par2, par3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void initGui() {
|
||||||
|
int x = width / 2;
|
||||||
|
int y = height / 2;
|
||||||
|
for (IOptionWidget widget : widgets) widget.addButtons(buttonList, x, y);
|
||||||
|
addButtons(x, y);
|
||||||
|
updateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addButtons(int x, int y) {}
|
||||||
|
|
||||||
|
protected void updateButtons() {}
|
||||||
|
|
||||||
|
protected void onButtonPress(int id) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void actionPerformed(GuiButton button) {
|
||||||
|
super.actionPerformed(button);
|
||||||
|
for (IOptionWidget widget : widgets) widget.onAction(button.id);
|
||||||
|
onButtonPress(button.id);
|
||||||
|
updateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void setButtonOptionBoolean(int id, String msgKey, boolean option) {
|
||||||
|
for (GuiButton button : (List<GuiButton>) buttonList) {
|
||||||
|
if (button.id == id) {
|
||||||
|
String optionText = option ? (EnumChatFormatting.GREEN + I18n.format("message.betterfoliage.optionOn")) : (EnumChatFormatting.RED + I18n.format("message.betterfoliage.optionOff"));
|
||||||
|
button.displayString = I18n.format(msgKey, optionText);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void setButtonOptionBoolean(int id, String msgKey, String optionKey) {
|
||||||
|
for (GuiButton button : (List<GuiButton>) buttonList) {
|
||||||
|
if (button.id == id) {
|
||||||
|
button.displayString = I18n.format(msgKey, I18n.format(optionKey));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package mods.betterfoliage.client.gui.widget;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.FontRenderer;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
|
||||||
|
public interface IOptionWidget {
|
||||||
|
|
||||||
|
public void addButtons(List<GuiButton> buttonList, int xOffset, int yOffset);
|
||||||
|
public void drawStrings(GuiScreen screen, FontRenderer fontRenderer, int xOffset, int yOffset, int labelColor, int numColor);
|
||||||
|
public void onAction(int buttonId);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package mods.betterfoliage.client.gui.widget;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
import mods.betterfoliage.common.config.OptionDouble;
|
||||||
|
import net.minecraft.client.gui.FontRenderer;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class OptionDoubleWidget implements IOptionWidget {
|
||||||
|
|
||||||
|
public OptionDouble option;
|
||||||
|
public int x;
|
||||||
|
public int y;
|
||||||
|
public int width;
|
||||||
|
public int numWidth;
|
||||||
|
public int idDecrement;
|
||||||
|
public int idIncrement;
|
||||||
|
public String keyLabel;
|
||||||
|
public String formatString;
|
||||||
|
|
||||||
|
public OptionDoubleWidget(OptionDouble option, int x, int y, int width, int numWidth, int idDecrement, int idIncrement, String keyLabel, String formatString) {
|
||||||
|
this.option = option;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.width = width;
|
||||||
|
this.numWidth = numWidth;
|
||||||
|
this.idDecrement = idDecrement;
|
||||||
|
this.idIncrement = idIncrement;
|
||||||
|
this.keyLabel = keyLabel;
|
||||||
|
this.formatString = formatString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addButtons(List<GuiButton> buttonList, int xOffset, int yOffset) {
|
||||||
|
buttonList.add(new GuiButton(idDecrement, xOffset + x + width - numWidth - 40, yOffset + y, 20, 20, "-"));
|
||||||
|
buttonList.add(new GuiButton(idIncrement, xOffset + x + width - 20, yOffset + y, 20, 20, "+"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawStrings(GuiScreen screen, FontRenderer fontRenderer, int xOffset, int yOffset, int labelColor, int numColor) {
|
||||||
|
screen.drawString(fontRenderer, I18n.format(keyLabel), xOffset + x, yOffset + y + 5, labelColor);
|
||||||
|
screen.drawCenteredString(fontRenderer, String.format(formatString, option.value), xOffset + x + width - 20 - numWidth / 2, yOffset + y + 5, numColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAction(int buttonId) {
|
||||||
|
if (buttonId == idDecrement) option.decrement();
|
||||||
|
if (buttonId == idIncrement) option.increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package mods.betterfoliage.client.gui.widget;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import mods.betterfoliage.common.config.OptionInteger;
|
||||||
|
import net.minecraft.client.gui.FontRenderer;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class OptionIntegerWidget implements IOptionWidget {
|
||||||
|
|
||||||
|
public OptionInteger option;
|
||||||
|
public int x;
|
||||||
|
public int y;
|
||||||
|
public int width;
|
||||||
|
public int numWidth;
|
||||||
|
public int idDecrement;
|
||||||
|
public int idIncrement;
|
||||||
|
public String keyLabel;
|
||||||
|
|
||||||
|
public OptionIntegerWidget(OptionInteger option, int x, int y, int width, int numWidth, int idDecrement, int idIncrement, String keyLabel) {
|
||||||
|
this.option = option;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.width = width;
|
||||||
|
this.numWidth = numWidth;
|
||||||
|
this.idDecrement = idDecrement;
|
||||||
|
this.idIncrement = idIncrement;
|
||||||
|
this.keyLabel = keyLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addButtons(List<GuiButton> buttonList, int xOffset, int yOffset) {
|
||||||
|
buttonList.add(new GuiButton(idDecrement, xOffset + x + width - numWidth - 40, yOffset + y, 20, 20, "-"));
|
||||||
|
buttonList.add(new GuiButton(idIncrement, xOffset + x + width - 20, yOffset + y, 20, 20, "+"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawStrings(GuiScreen screen, FontRenderer fontRenderer, int xOffset, int yOffset, int labelColor, int numColor) {
|
||||||
|
screen.drawString(fontRenderer, I18n.format(keyLabel), xOffset + x, yOffset + y + 5, labelColor);
|
||||||
|
screen.drawCenteredString(fontRenderer, Integer.toString(option.value), xOffset + x + width - 20 - numWidth / 2, yOffset + y + 5, numColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAction(int buttonId) {
|
||||||
|
if (buttonId == idDecrement) option.decrement();
|
||||||
|
if (buttonId == idIncrement) option.increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package mods.betterfoliage.client.render;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
|
||||||
|
/** Same as {@link RenderBlockAOBase}, but does not actually render anything.
|
||||||
|
* @author octarine-noise
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class FakeRenderBlockAOBase extends RenderBlockAOBase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceZNeg(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
saveShadingTopLeft(aoZNXYPP);
|
||||||
|
saveShadingTopRight(aoZNXYNP);
|
||||||
|
saveShadingBottomLeft(aoZNXYPN);
|
||||||
|
saveShadingBottomRight(aoZNXYNN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceZPos(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
saveShadingTopLeft(aoZPXYNP);
|
||||||
|
saveShadingTopRight(aoZPXYPP);
|
||||||
|
saveShadingBottomLeft(aoZPXYNN);
|
||||||
|
saveShadingBottomRight(aoZPXYPN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceXNeg(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
saveShadingTopLeft(aoXNYZPN);
|
||||||
|
saveShadingTopRight(aoXNYZPP);
|
||||||
|
saveShadingBottomLeft(aoXNYZNN);
|
||||||
|
saveShadingBottomRight(aoXNYZNP);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceXPos(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
saveShadingTopLeft(aoXPYZPP);
|
||||||
|
saveShadingTopRight(aoXPYZPN);
|
||||||
|
saveShadingBottomLeft(aoXPYZNP);
|
||||||
|
saveShadingBottomRight(aoXPYZNN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceYNeg(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
saveShadingTopLeft(aoYNXZNP);
|
||||||
|
saveShadingTopRight(aoYNXZPP);
|
||||||
|
saveShadingBottomLeft(aoYNXZNN);
|
||||||
|
saveShadingBottomRight(aoYNXZPN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceYPos(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
saveShadingTopLeft(aoYPXZPP);
|
||||||
|
saveShadingTopRight(aoYPXZNP);
|
||||||
|
saveShadingBottomLeft(aoYPXZPN);
|
||||||
|
saveShadingBottomRight(aoYPXZNN);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package mods.betterfoliage.client.render;
|
||||||
|
|
||||||
|
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public interface IRenderBlockDecorator extends ISimpleBlockRenderingHandler {
|
||||||
|
|
||||||
|
public void init();
|
||||||
|
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original);
|
||||||
|
|
||||||
|
}
|
||||||
52
src/main/java/mods/betterfoliage/client/render/IconSet.java
Normal file
52
src/main/java/mods/betterfoliage/client/render/IconSet.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package mods.betterfoliage.client.render;
|
||||||
|
|
||||||
|
import mods.betterfoliage.common.util.Utils;
|
||||||
|
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
/** Loads an indexed set of textures
|
||||||
|
* @author octarine-noise
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class IconSet {
|
||||||
|
|
||||||
|
/** Icon array */
|
||||||
|
public IIcon[] icons = new IIcon[16];
|
||||||
|
|
||||||
|
/** Number of successfully loaded icons*/
|
||||||
|
public int numLoaded = 0;
|
||||||
|
|
||||||
|
/** Resource domain of icons */
|
||||||
|
String domain;
|
||||||
|
|
||||||
|
/** Format string of icon paths */
|
||||||
|
String path;
|
||||||
|
|
||||||
|
public IconSet(String domain, String path) {
|
||||||
|
this.domain = domain;
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerIcons(IIconRegister register) {
|
||||||
|
numLoaded = 0;
|
||||||
|
for (int idx = 0; idx < 16; idx++) {
|
||||||
|
icons[idx] = null;
|
||||||
|
// if the path contains a domain, use that to check if the resource exists
|
||||||
|
String resolvedDomain = path.contains(":") ? new ResourceLocation(path).getResourceDomain() : domain;
|
||||||
|
String resolvedPath = String.format("textures/blocks/" + (path.contains(":") ? new ResourceLocation(path).getResourcePath() : path) + ".png", idx);
|
||||||
|
if (Utils.resourceExists(new ResourceLocation(resolvedDomain, resolvedPath)))
|
||||||
|
icons[numLoaded++] = register.registerIcon(domain + ":" + String.format(path, idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IIcon get(int variation) {
|
||||||
|
return numLoaded == 0 ? null : icons[variation % numLoaded];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasIcons() {
|
||||||
|
return numLoaded > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,440 @@
|
|||||||
|
package mods.betterfoliage.client.render;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import mods.betterfoliage.common.util.Double3;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.util.MathHelper;
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
/** Block renderer base class. Stores calculated ambient occlusion light and color values when rendering
|
||||||
|
* block sides for later use.
|
||||||
|
* @author octarine-noise
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class RenderBlockAOBase extends RenderBlocks {
|
||||||
|
|
||||||
|
/** AO light and color values
|
||||||
|
* @author octarine-noise
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public static class ShadingValues {
|
||||||
|
public int passCounter = 0;
|
||||||
|
public int brightness;
|
||||||
|
public float red;
|
||||||
|
public float green;
|
||||||
|
public float blue;
|
||||||
|
public void setGray(float value) {
|
||||||
|
red = value; green = value; blue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected double[] uValues = new double[] {0.0, 16.0, 16.0, 0.0};
|
||||||
|
protected double[] vValues = new double[] {0.0, 0.0, 16.0, 16.0};
|
||||||
|
|
||||||
|
protected ForgeDirection[] faceDir1 = new ForgeDirection[] {ForgeDirection.WEST, ForgeDirection.WEST, ForgeDirection.WEST, ForgeDirection.EAST, ForgeDirection.SOUTH, ForgeDirection.NORTH};
|
||||||
|
protected ForgeDirection[] faceDir2 = new ForgeDirection[] {ForgeDirection.NORTH, ForgeDirection.SOUTH, ForgeDirection.UP, ForgeDirection.UP, ForgeDirection.UP, ForgeDirection.UP};
|
||||||
|
|
||||||
|
/** Random vector pool. Unit rotation vectors in the XZ plane, Y coord goes between [-1.0, 1.0].
|
||||||
|
* Filled at init time */
|
||||||
|
public Double3[] pRot = new Double3[64];
|
||||||
|
|
||||||
|
/** Pool of random double values. Filled at init time. */
|
||||||
|
public double[] pRand = new double[64];
|
||||||
|
|
||||||
|
public ShadingValues aoXPYZPP = new ShadingValues();
|
||||||
|
public ShadingValues aoXPYZPN = new ShadingValues();
|
||||||
|
public ShadingValues aoXPYZNP = new ShadingValues();
|
||||||
|
public ShadingValues aoXPYZNN = new ShadingValues();
|
||||||
|
public ShadingValues aoXNYZPP = new ShadingValues();
|
||||||
|
public ShadingValues aoXNYZPN = new ShadingValues();
|
||||||
|
public ShadingValues aoXNYZNP = new ShadingValues();
|
||||||
|
public ShadingValues aoXNYZNN = new ShadingValues();
|
||||||
|
public ShadingValues aoYPXZPP = new ShadingValues();
|
||||||
|
public ShadingValues aoYPXZPN = new ShadingValues();
|
||||||
|
public ShadingValues aoYPXZNP = new ShadingValues();
|
||||||
|
public ShadingValues aoYPXZNN = new ShadingValues();
|
||||||
|
public ShadingValues aoYNXZPP = new ShadingValues();
|
||||||
|
public ShadingValues aoYNXZPN = new ShadingValues();
|
||||||
|
public ShadingValues aoYNXZNP = new ShadingValues();
|
||||||
|
public ShadingValues aoYNXZNN = new ShadingValues();
|
||||||
|
public ShadingValues aoZPXYPP = new ShadingValues();
|
||||||
|
public ShadingValues aoZPXYPN = new ShadingValues();
|
||||||
|
public ShadingValues aoZPXYNP = new ShadingValues();
|
||||||
|
public ShadingValues aoZPXYNN = new ShadingValues();
|
||||||
|
public ShadingValues aoZNXYPP = new ShadingValues();
|
||||||
|
public ShadingValues aoZNXYPN = new ShadingValues();
|
||||||
|
public ShadingValues aoZNXYNP = new ShadingValues();
|
||||||
|
public ShadingValues aoZNXYNN = new ShadingValues();
|
||||||
|
|
||||||
|
// temporary shading values for a single face
|
||||||
|
public ShadingValues faceAOPP, faceAOPN, faceAONN, faceAONP;
|
||||||
|
|
||||||
|
/** Initialize random values */
|
||||||
|
public void init() {
|
||||||
|
List<Double3> perturbs = new ArrayList<Double3>(64);
|
||||||
|
for (int idx = 0; idx < 64; idx++) {
|
||||||
|
double angle = (double) idx * Math.PI * 2.0 / 64.0;
|
||||||
|
perturbs.add(new Double3(Math.cos(angle), Math.random() * 2.0 - 1.0, Math.sin(angle)));
|
||||||
|
pRand[idx] = Math.random();
|
||||||
|
}
|
||||||
|
Collections.shuffle(perturbs);
|
||||||
|
Iterator<Double3> iter = perturbs.iterator();
|
||||||
|
for (int idx = 0; idx < 64; idx++) pRot[idx] = iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a semi-random value depending on block position.
|
||||||
|
* @param x block X coord
|
||||||
|
* @param y block Y coord
|
||||||
|
* @param z block Z coord
|
||||||
|
* @param seed additional seed
|
||||||
|
* @return semirandom value
|
||||||
|
*/
|
||||||
|
protected int getSemiRandomFromPos(double x, double y, double z, int seed) {
|
||||||
|
long lx = MathHelper.floor_double(x);
|
||||||
|
long ly = MathHelper.floor_double(y);
|
||||||
|
long lz = MathHelper.floor_double(z);
|
||||||
|
long value = (lx * lx + ly * ly + lz * lz + lx * ly + ly * lz + lz * lx + seed * seed) & 63;
|
||||||
|
value = (3 * lx * value + 5 * ly * value + 7 * lz * value + 11 * seed) & 63;
|
||||||
|
return (int) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderInventoryBlock(Block block, int metadata, int modelId, RenderBlocks renderer) {
|
||||||
|
renderStandardBlockAsItem(renderer, block, metadata, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldRender3DInInventory(int modelId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRenderId() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderStandardBlockAsItem(RenderBlocks renderer, Block p_147800_1_, int p_147800_2_, float p_147800_3_) {
|
||||||
|
Tessellator tessellator = Tessellator.instance;
|
||||||
|
boolean flag = p_147800_1_ == Blocks.grass;
|
||||||
|
|
||||||
|
float f2;
|
||||||
|
float f3;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
p_147800_1_.setBlockBoundsForItemRender();
|
||||||
|
renderer.setRenderBoundsFromBlock(p_147800_1_);
|
||||||
|
GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F);
|
||||||
|
GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
|
||||||
|
tessellator.startDrawingQuads();
|
||||||
|
tessellator.setNormal(0.0F, -1.0F, 0.0F);
|
||||||
|
renderer.renderFaceYNeg(p_147800_1_, 0.0D, 0.0D, 0.0D, renderer.getBlockIconFromSideAndMetadata(p_147800_1_, 0, p_147800_2_));
|
||||||
|
tessellator.draw();
|
||||||
|
|
||||||
|
if (flag && renderer.useInventoryTint)
|
||||||
|
{
|
||||||
|
k = p_147800_1_.getRenderColor(p_147800_2_);
|
||||||
|
f2 = (float)(k >> 16 & 255) / 255.0F;
|
||||||
|
f3 = (float)(k >> 8 & 255) / 255.0F;
|
||||||
|
float f4 = (float)(k & 255) / 255.0F;
|
||||||
|
GL11.glColor4f(f2 * p_147800_3_, f3 * p_147800_3_, f4 * p_147800_3_, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
tessellator.startDrawingQuads();
|
||||||
|
tessellator.setNormal(0.0F, 1.0F, 0.0F);
|
||||||
|
renderer.renderFaceYPos(p_147800_1_, 0.0D, 0.0D, 0.0D, renderer.getBlockIconFromSideAndMetadata(p_147800_1_, 1, p_147800_2_));
|
||||||
|
tessellator.draw();
|
||||||
|
|
||||||
|
if (flag && renderer.useInventoryTint)
|
||||||
|
{
|
||||||
|
GL11.glColor4f(p_147800_3_, p_147800_3_, p_147800_3_, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
tessellator.startDrawingQuads();
|
||||||
|
tessellator.setNormal(0.0F, 0.0F, -1.0F);
|
||||||
|
renderer.renderFaceZNeg(p_147800_1_, 0.0D, 0.0D, 0.0D, renderer.getBlockIconFromSideAndMetadata(p_147800_1_, 2, p_147800_2_));
|
||||||
|
tessellator.draw();
|
||||||
|
tessellator.startDrawingQuads();
|
||||||
|
tessellator.setNormal(0.0F, 0.0F, 1.0F);
|
||||||
|
renderer.renderFaceZPos(p_147800_1_, 0.0D, 0.0D, 0.0D, renderer.getBlockIconFromSideAndMetadata(p_147800_1_, 3, p_147800_2_));
|
||||||
|
tessellator.draw();
|
||||||
|
tessellator.startDrawingQuads();
|
||||||
|
tessellator.setNormal(-1.0F, 0.0F, 0.0F);
|
||||||
|
renderer.renderFaceXNeg(p_147800_1_, 0.0D, 0.0D, 0.0D, renderer.getBlockIconFromSideAndMetadata(p_147800_1_, 4, p_147800_2_));
|
||||||
|
tessellator.draw();
|
||||||
|
tessellator.startDrawingQuads();
|
||||||
|
tessellator.setNormal(1.0F, 0.0F, 0.0F);
|
||||||
|
renderer.renderFaceXPos(p_147800_1_, 0.0D, 0.0D, 0.0D, renderer.getBlockIconFromSideAndMetadata(p_147800_1_, 5, p_147800_2_));
|
||||||
|
tessellator.draw();
|
||||||
|
GL11.glTranslatef(0.5F, 0.5F, 0.5F);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setShadingForFace(ForgeDirection dir) {
|
||||||
|
if (dir == ForgeDirection.DOWN) {
|
||||||
|
// dir1 WEST, dir2 NORTH
|
||||||
|
faceAOPP = aoYNXZPP; faceAOPN = aoYNXZPN; faceAONN = aoYNXZNN; faceAONP = aoYNXZNP;
|
||||||
|
} else if (dir == ForgeDirection.UP) {
|
||||||
|
// dir1 WEST, dir2 SOUTH
|
||||||
|
faceAOPP = aoYPXZPP; faceAOPN = aoYPXZPN; faceAONN = aoYPXZNN; faceAONP = aoYPXZNP;
|
||||||
|
} else if (dir == ForgeDirection.NORTH) {
|
||||||
|
// dir1 WEST, dir2 UP
|
||||||
|
faceAOPP = aoZNXYNP; faceAOPN = aoZNXYNN; faceAONN = aoZNXYPN; faceAONP = aoZNXYPP;
|
||||||
|
} else if (dir == ForgeDirection.SOUTH) {
|
||||||
|
// dir1 EAST, dir2 UP
|
||||||
|
faceAOPP = aoZPXYPP; faceAOPN = aoZPXYPN; faceAONN = aoZPXYNN; faceAONP = aoZPXYNP;
|
||||||
|
} else if (dir == ForgeDirection.WEST) {
|
||||||
|
// dir1 SOUTH, dir2 UP
|
||||||
|
faceAOPP = aoXNYZPP; faceAOPN = aoXNYZNP; faceAONN = aoXNYZNN; faceAONP = aoXNYZPN;
|
||||||
|
} else if (dir == ForgeDirection.EAST) {
|
||||||
|
// dir1 NORTH, dir2 UP
|
||||||
|
faceAOPP = aoXPYZPN; faceAOPN = aoXPYZNN; faceAONN = aoXPYZNP; faceAONP = aoXPYZPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderCrossedSideQuads(Double3 drawBase, ForgeDirection dir, double scale, double halfHeight, Double3 rendomVec, double offset, IIcon renderIcon, int uvRot, boolean noShading) {
|
||||||
|
Double3 facePP, faceNP, faceNormal, drawCenter;
|
||||||
|
|
||||||
|
if (dir == ForgeDirection.UP) {
|
||||||
|
// special case for block top, we'll be rendering a LOT of those
|
||||||
|
facePP = new Double3(-scale, 0.0, scale);
|
||||||
|
faceNP = new Double3(scale, 0.0, scale);
|
||||||
|
faceNormal = new Double3(0.0, halfHeight, 0.0);
|
||||||
|
drawCenter = drawBase.add(faceNormal);
|
||||||
|
if (rendomVec != null) {
|
||||||
|
drawCenter = drawBase.add(faceNormal).add(rendomVec.scaleAxes(-offset, 0.0, offset));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
facePP = new Double3(faceDir1[dir.ordinal()]).add(new Double3(faceDir2[dir.ordinal()])).scale(scale);
|
||||||
|
faceNP = new Double3(faceDir1[dir.ordinal()]).inverse().add(new Double3(faceDir2[dir.ordinal()])).scale(scale);
|
||||||
|
faceNormal = new Double3(dir).scale(halfHeight);
|
||||||
|
drawCenter = drawBase.add(faceNormal);
|
||||||
|
if (rendomVec != null) {
|
||||||
|
drawCenter = drawCenter.add(new Double3(faceDir1[dir.ordinal()]).scale(rendomVec.x).scale(offset))
|
||||||
|
.add(new Double3(faceDir2[dir.ordinal()]).scale(rendomVec.z).scale(offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Minecraft.isAmbientOcclusionEnabled() && !noShading) {
|
||||||
|
setShadingForFace(dir);
|
||||||
|
renderQuadWithShading(renderIcon, drawCenter, facePP, faceNormal, uvRot, faceAOPP, faceAONN, faceAONN, faceAOPP);
|
||||||
|
renderQuadWithShading(renderIcon, drawCenter, facePP.inverse(), faceNormal, uvRot, faceAONN, faceAOPP, faceAOPP, faceAONN);
|
||||||
|
renderQuadWithShading(renderIcon, drawCenter, faceNP, faceNormal, uvRot, faceAONP, faceAOPN, faceAOPN, faceAONP);
|
||||||
|
renderQuadWithShading(renderIcon, drawCenter, faceNP.inverse(), faceNormal, uvRot, faceAOPN, faceAONP, faceAONP, faceAOPN);
|
||||||
|
} else {
|
||||||
|
renderQuad(renderIcon, drawCenter, facePP, faceNormal, uvRot);
|
||||||
|
renderQuad(renderIcon, drawCenter, facePP.inverse(), faceNormal, uvRot);
|
||||||
|
renderQuad(renderIcon, drawCenter, faceNP, faceNormal, uvRot);
|
||||||
|
renderQuad(renderIcon, drawCenter, faceNP.inverse(), faceNormal, uvRot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderCrossedBlockQuadsTranslate(Double3 blockCenter, double halfSize, Double3 offsetVec, IIcon crossLeafIcon, int uvRot, boolean isAirTop, boolean isAirBottom) {
|
||||||
|
Double3 drawCenter = blockCenter;
|
||||||
|
if (offsetVec != null) drawCenter = drawCenter.add(offsetVec);
|
||||||
|
Double3 horz1 = new Double3(halfSize, 0.0, halfSize);
|
||||||
|
Double3 horz2 = new Double3(halfSize, 0.0, -halfSize);
|
||||||
|
Double3 vert1 = new Double3(0.0, halfSize * 1.41, 0.0);
|
||||||
|
|
||||||
|
renderCrossedBlockQuadsInternal(drawCenter, horz1, horz2, vert1, crossLeafIcon, uvRot, isAirTop, isAirBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderCrossedBlockQuadsSkew(Double3 blockCenter, double halfSize, Double3 offsetVec1, Double3 offsetVec2, IIcon crossLeafIcon, int uvRot, boolean isAirTop, boolean isAirBottom) {
|
||||||
|
Double3 horz1 = new Double3(halfSize, 0.0, halfSize).add(offsetVec1);
|
||||||
|
Double3 horz2 = new Double3(halfSize, 0.0, -halfSize).add(offsetVec2);
|
||||||
|
Double3 vert1 = new Double3(0.0, halfSize * 1.41, 0.0);
|
||||||
|
|
||||||
|
renderCrossedBlockQuadsInternal(blockCenter, horz1, horz2, vert1, crossLeafIcon, uvRot, isAirTop, isAirBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderCrossedBlockQuadsInternal(Double3 drawCenter, Double3 horz1, Double3 horz2, Double3 vert1, IIcon crossLeafIcon, int uvRot, boolean isAirTop, boolean isAirBottom) {
|
||||||
|
if (Minecraft.isAmbientOcclusionEnabled()) {
|
||||||
|
renderQuadWithShading(crossLeafIcon, drawCenter, horz1, vert1, uvRot,
|
||||||
|
isAirTop ? aoYPXZPP : aoZPXYPP, isAirTop ? aoYPXZNN : aoXNYZPN, isAirBottom ? aoYNXZNN : aoXNYZNN, isAirBottom ? aoYNXZPP : aoZPXYPN);
|
||||||
|
renderQuadWithShading(crossLeafIcon, drawCenter, horz1.inverse(), vert1, uvRot,
|
||||||
|
isAirTop ? aoYPXZNN : aoZNXYNP, isAirTop ? aoYPXZPP : aoXPYZPP, isAirBottom ? aoYNXZPP : aoXPYZNP, isAirBottom ? aoYNXZNN : aoZNXYNN);
|
||||||
|
renderQuadWithShading(crossLeafIcon, drawCenter, horz2, vert1, uvRot,
|
||||||
|
isAirTop ? aoYPXZPN : aoXPYZPN, isAirTop ? aoYPXZNP : aoZPXYNP, isAirBottom ? aoYNXZNP : aoZPXYNN, isAirBottom ? aoYNXZPN : aoXPYZNN);
|
||||||
|
renderQuadWithShading(crossLeafIcon, drawCenter, horz2.inverse(), vert1, uvRot,
|
||||||
|
isAirTop ? aoYPXZNP : aoXNYZPP, isAirTop ? aoYPXZPN : aoZNXYPP, isAirBottom ? aoYNXZPN : aoZNXYPN, isAirBottom ? aoYNXZNP : aoXNYZNP);
|
||||||
|
} else {
|
||||||
|
renderQuad(crossLeafIcon, drawCenter, horz1, vert1, uvRot);
|
||||||
|
renderQuad(crossLeafIcon, drawCenter, horz1.inverse(), vert1, uvRot);
|
||||||
|
renderQuad(crossLeafIcon, drawCenter, horz2, vert1, uvRot);
|
||||||
|
renderQuad(crossLeafIcon, drawCenter, horz2.inverse(), vert1, uvRot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceZNeg(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
super.renderFaceZNeg(block, x, y, z, icon);
|
||||||
|
saveShadingTopLeft(aoZNXYPP);
|
||||||
|
saveShadingTopRight(aoZNXYNP);
|
||||||
|
saveShadingBottomLeft(aoZNXYPN);
|
||||||
|
saveShadingBottomRight(aoZNXYNN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceZPos(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
super.renderFaceZPos(block, x, y, z, icon);
|
||||||
|
saveShadingTopLeft(aoZPXYNP);
|
||||||
|
saveShadingTopRight(aoZPXYPP);
|
||||||
|
saveShadingBottomLeft(aoZPXYNN);
|
||||||
|
saveShadingBottomRight(aoZPXYPN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceXNeg(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
super.renderFaceXNeg(block, x, y, z, icon);
|
||||||
|
saveShadingTopLeft(aoXNYZPN);
|
||||||
|
saveShadingTopRight(aoXNYZPP);
|
||||||
|
saveShadingBottomLeft(aoXNYZNN);
|
||||||
|
saveShadingBottomRight(aoXNYZNP);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceXPos(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
super.renderFaceXPos(block, x, y, z, icon);
|
||||||
|
saveShadingTopLeft(aoXPYZPP);
|
||||||
|
saveShadingTopRight(aoXPYZPN);
|
||||||
|
saveShadingBottomLeft(aoXPYZNP);
|
||||||
|
saveShadingBottomRight(aoXPYZNN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceYNeg(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
super.renderFaceYNeg(block, x, y, z, icon);
|
||||||
|
saveShadingTopLeft(aoYNXZNP);
|
||||||
|
saveShadingTopRight(aoYNXZPP);
|
||||||
|
saveShadingBottomLeft(aoYNXZNN);
|
||||||
|
saveShadingBottomRight(aoYNXZPN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderFaceYPos(Block block, double x, double y, double z, IIcon icon) {
|
||||||
|
super.renderFaceYPos(block, x, y, z, icon);
|
||||||
|
saveShadingTopLeft(aoYPXZPP);
|
||||||
|
saveShadingTopRight(aoYPXZNP);
|
||||||
|
saveShadingBottomLeft(aoYPXZPN);
|
||||||
|
saveShadingBottomRight(aoYPXZNN);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void saveShadingTopLeft(ShadingValues values) {
|
||||||
|
if (--values.passCounter != 0) return;
|
||||||
|
values.brightness = brightnessTopLeft;
|
||||||
|
values.red = colorRedTopLeft;
|
||||||
|
values.green = colorGreenTopLeft;
|
||||||
|
values.blue = colorBlueTopLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void saveShadingTopRight(ShadingValues values) {
|
||||||
|
if (--values.passCounter != 0) return;
|
||||||
|
values.brightness = brightnessTopRight;
|
||||||
|
values.red = colorRedTopRight;
|
||||||
|
values.green = colorGreenTopRight;
|
||||||
|
values.blue = colorBlueTopRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void saveShadingBottomLeft(ShadingValues values) {
|
||||||
|
if (--values.passCounter != 0) return;
|
||||||
|
values.brightness = brightnessBottomLeft;
|
||||||
|
values.red = colorRedBottomLeft;
|
||||||
|
values.green = colorGreenBottomLeft;
|
||||||
|
values.blue = colorBlueBottomLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void saveShadingBottomRight(ShadingValues values) {
|
||||||
|
if (--values.passCounter != 0) return;
|
||||||
|
values.brightness = brightnessBottomRight;
|
||||||
|
values.red = colorRedBottomRight;
|
||||||
|
values.green = colorGreenBottomRight;
|
||||||
|
values.blue = colorBlueBottomRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set pass counter on all shading value objects.
|
||||||
|
* Used to collect AO values from a specific draw pass
|
||||||
|
* if the underlying renderer draws overlays
|
||||||
|
* @param value pass counter
|
||||||
|
*/
|
||||||
|
protected void setPassCounters(int value) {
|
||||||
|
aoXPYZPP.passCounter = value;
|
||||||
|
aoXPYZPN.passCounter = value;
|
||||||
|
aoXPYZNP.passCounter = value;
|
||||||
|
aoXPYZNN.passCounter = value;
|
||||||
|
aoXNYZPP.passCounter = value;
|
||||||
|
aoXNYZPN.passCounter = value;
|
||||||
|
aoXNYZNP.passCounter = value;
|
||||||
|
aoXNYZNN.passCounter = value;
|
||||||
|
aoYPXZPP.passCounter = value;
|
||||||
|
aoYPXZPN.passCounter = value;
|
||||||
|
aoYPXZNP.passCounter = value;
|
||||||
|
aoYPXZNN.passCounter = value;
|
||||||
|
aoYNXZPP.passCounter = value;
|
||||||
|
aoYNXZPN.passCounter = value;
|
||||||
|
aoYNXZNP.passCounter = value;
|
||||||
|
aoYNXZNN.passCounter = value;
|
||||||
|
aoZPXYPP.passCounter = value;
|
||||||
|
aoZPXYPN.passCounter = value;
|
||||||
|
aoZPXYNP.passCounter = value;
|
||||||
|
aoZPXYNN.passCounter = value;
|
||||||
|
aoZNXYPP.passCounter = value;
|
||||||
|
aoZNXYPN.passCounter = value;
|
||||||
|
aoZNXYNP.passCounter = value;
|
||||||
|
aoZNXYNN.passCounter = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Render textured quad
|
||||||
|
* @param icon texture to use
|
||||||
|
* @param center center of quad
|
||||||
|
* @param vec1 vector to the half-point of one of the sides
|
||||||
|
* @param vec2 vector to half-point of side next to vec1
|
||||||
|
* @param uvRot number of increments to rotate UV coordinates by
|
||||||
|
*/
|
||||||
|
protected void renderQuad(IIcon icon, Double3 center, Double3 vec1, Double3 vec2, int uvRot) {
|
||||||
|
Tessellator tessellator = Tessellator.instance;
|
||||||
|
tessellator.addVertexWithUV(center.x + vec1.x + vec2.x, center.y + vec1.y + vec2.y, center.z + vec1.z + vec2.z, icon.getInterpolatedU(uValues[uvRot & 3]), icon.getInterpolatedV(vValues[uvRot & 3]));
|
||||||
|
tessellator.addVertexWithUV(center.x - vec1.x + vec2.x, center.y - vec1.y + vec2.y, center.z - vec1.z + vec2.z, icon.getInterpolatedU(uValues[(uvRot + 1) & 3]), icon.getInterpolatedV(vValues[(uvRot + 1) & 3]));
|
||||||
|
tessellator.addVertexWithUV(center.x - vec1.x - vec2.x, center.y - vec1.y - vec2.y, center.z - vec1.z - vec2.z, icon.getInterpolatedU(uValues[(uvRot + 2) & 3]), icon.getInterpolatedV(vValues[(uvRot + 2) & 3]));
|
||||||
|
tessellator.addVertexWithUV(center.x + vec1.x - vec2.x, center.y + vec1.y - vec2.y, center.z + vec1.z - vec2.z, icon.getInterpolatedU(uValues[(uvRot + 3) & 3]), icon.getInterpolatedV(vValues[(uvRot + 3) & 3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Render textured quad using AO information
|
||||||
|
* @param icon texture to use
|
||||||
|
* @param center center of quad
|
||||||
|
* @param vec1 vector to the half-point of one of the sides
|
||||||
|
* @param vec2 vector to half-point of side next to vec1
|
||||||
|
* @param uvRot number of increments to rotate UV coordinates by
|
||||||
|
* @param aoPP AO values for vertex at (+vec1, +vec2)
|
||||||
|
* @param aoNP AO values for vertex at (-vec1, +vec2)
|
||||||
|
* @param aoNN AO values for vertex at (-vec1, -vec2)
|
||||||
|
* @param aoPN AO values for vertex at (+vec1, -vec2)
|
||||||
|
*/
|
||||||
|
protected void renderQuadWithShading(IIcon icon, Double3 center, Double3 vec1, Double3 vec2, int uvRot, ShadingValues aoPP, ShadingValues aoNP, ShadingValues aoNN, ShadingValues aoPN) {
|
||||||
|
Tessellator tessellator = Tessellator.instance;
|
||||||
|
tessellator.setBrightness(aoPP.brightness);
|
||||||
|
tessellator.setColorOpaque_F(aoPP.red, aoPP.green, aoPP.blue);
|
||||||
|
tessellator.addVertexWithUV(center.x + vec1.x + vec2.x, center.y + vec1.y + vec2.y, center.z + vec1.z + vec2.z, icon.getInterpolatedU(uValues[uvRot & 3]), icon.getInterpolatedV(vValues[uvRot & 3]));
|
||||||
|
tessellator.setBrightness(aoNP.brightness);
|
||||||
|
tessellator.setColorOpaque_F(aoNP.red, aoNP.green, aoNP.blue);
|
||||||
|
tessellator.addVertexWithUV(center.x - vec1.x + vec2.x, center.y - vec1.y + vec2.y, center.z - vec1.z + vec2.z, icon.getInterpolatedU(uValues[(uvRot + 1) & 3]), icon.getInterpolatedV(vValues[(uvRot + 1) & 3]));
|
||||||
|
tessellator.setBrightness(aoNN.brightness);
|
||||||
|
tessellator.setColorOpaque_F(aoNN.red, aoNN.green, aoNN.blue);
|
||||||
|
tessellator.addVertexWithUV(center.x - vec1.x - vec2.x, center.y - vec1.y - vec2.y, center.z - vec1.z - vec2.z, icon.getInterpolatedU(uValues[(uvRot + 2) & 3]), icon.getInterpolatedV(vValues[(uvRot + 2) & 3]));
|
||||||
|
tessellator.setBrightness(aoPN.brightness);
|
||||||
|
tessellator.setColorOpaque_F(aoPN.red, aoPN.green, aoPN.blue);
|
||||||
|
tessellator.addVertexWithUV(center.x + vec1.x - vec2.x, center.y + vec1.y - vec2.y, center.z + vec1.z - vec2.z, icon.getInterpolatedU(uValues[(uvRot + 3) & 3]), icon.getInterpolatedV(vValues[(uvRot + 3) & 3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getBrightness(Block block, int x, int y, int z) {
|
||||||
|
return block.getMixedBrightnessForBlock(blockAccess, x, y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package mods.betterfoliage.client.render.impl;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
||||||
|
import mods.betterfoliage.client.render.IconSet;
|
||||||
|
import mods.betterfoliage.client.render.RenderBlockAOBase;
|
||||||
|
import mods.betterfoliage.common.util.Double3;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockDirt;
|
||||||
|
import net.minecraft.block.material.Material;
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.util.MathHelper;
|
||||||
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
import net.minecraft.world.gen.NoiseGeneratorSimplex;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class RenderBlockBetterAlgae extends RenderBlockAOBase implements IRenderBlockDecorator {
|
||||||
|
|
||||||
|
public IconSet algaeIcons = new IconSet("bettergrassandleaves", "better_algae_%d");
|
||||||
|
public NoiseGeneratorSimplex noise;
|
||||||
|
|
||||||
|
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
|
||||||
|
if (!BetterFoliage.config.algaeEnabled) return false;
|
||||||
|
if (y >= 254 || !(block instanceof BlockDirt)) return false;
|
||||||
|
if (blockAccess.getBlock(x, y + 1, z).getMaterial() != Material.water) return false;
|
||||||
|
if (blockAccess.getBlock(x, y + 2, z).getMaterial() != Material.water) return false;
|
||||||
|
if (blockAccess.getBiomeGenForCoords(x, z).temperature < 0.4f) return false;
|
||||||
|
int terrainVariation = MathHelper.floor_double((noise.func_151605_a(x, z) + 1.0) * 32.0);
|
||||||
|
return terrainVariation < BetterFoliage.config.algaeChance.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
|
||||||
|
// store world for later use
|
||||||
|
blockAccess = world;
|
||||||
|
|
||||||
|
// render dirt block
|
||||||
|
setPassCounters(1);
|
||||||
|
setRenderBoundsFromBlock(block);
|
||||||
|
renderStandardBlock(block, x, y, z);
|
||||||
|
|
||||||
|
int variation = getSemiRandomFromPos(x, y, z, 0);
|
||||||
|
int heightVariation = getSemiRandomFromPos(x, y, z, 1);
|
||||||
|
|
||||||
|
IIcon renderIcon = algaeIcons.get(variation);
|
||||||
|
if (renderIcon == null) return true;
|
||||||
|
|
||||||
|
double scale = BetterFoliage.config.algaeSize.value * 0.5;
|
||||||
|
double halfHeight = 0.5 * (BetterFoliage.config.algaeHeightMin.value + pRand[heightVariation] * (BetterFoliage.config.algaeHeightMax.value - BetterFoliage.config.algaeHeightMin.value));
|
||||||
|
Tessellator.instance.setBrightness(getBrightness(block, x, y + 1, z));
|
||||||
|
renderCrossedSideQuads(new Double3(x + 0.5, y + 1.0 - 0.125 * halfHeight, z + 0.5), ForgeDirection.UP, scale, halfHeight, pRot[variation], BetterFoliage.config.algaeHOffset.value, renderIcon, 0, false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleTextureReload(TextureStitchEvent.Pre event) {
|
||||||
|
if (event.map.getTextureType() != 0) return;
|
||||||
|
|
||||||
|
algaeIcons.registerIcons(event.map);
|
||||||
|
BetterFoliage.log.info(String.format("Found %d algae textures", algaeIcons.numLoaded));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleWorldLoad(WorldEvent.Load event) {
|
||||||
|
noise = new NoiseGeneratorSimplex(new Random(event.world.getWorldInfo().getSeed() + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package mods.betterfoliage.client.render.impl;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.render.FakeRenderBlockAOBase;
|
||||||
|
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
||||||
|
import mods.betterfoliage.client.render.IconSet;
|
||||||
|
import mods.betterfoliage.common.util.Double3;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class RenderBlockBetterCactus extends FakeRenderBlockAOBase implements IRenderBlockDecorator {
|
||||||
|
|
||||||
|
public IIcon cactusRoundIcon;
|
||||||
|
public IconSet cactusSideIcons = new IconSet("bettergrassandleaves", "better_cactus_arm_%d");
|
||||||
|
|
||||||
|
public static ForgeDirection[] cactusDirections = new ForgeDirection[] { ForgeDirection.NORTH, ForgeDirection.SOUTH, ForgeDirection.EAST, ForgeDirection.WEST};
|
||||||
|
public static double cactusRadius = 0.4375;
|
||||||
|
|
||||||
|
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
|
||||||
|
return BetterFoliage.config.cactusEnabled && block == Blocks.cactus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
|
||||||
|
// store world for later use
|
||||||
|
blockAccess = world;
|
||||||
|
|
||||||
|
// render cactus center
|
||||||
|
setPassCounters(1);
|
||||||
|
setRenderBoundsFromBlock(block);
|
||||||
|
|
||||||
|
Double3 blockCenter = new Double3(x + 0.5, y + 0.5, z + 0.5);
|
||||||
|
renderStandardBlock(block, x, y, z);
|
||||||
|
Tessellator.instance.setBrightness(getBrightness(block,x, y, z));
|
||||||
|
renderCactusCore(block.getBlockTextureFromSide(ForgeDirection.UP.ordinal()),
|
||||||
|
block.getBlockTextureFromSide(ForgeDirection.NORTH.ordinal()),
|
||||||
|
blockCenter, 0);
|
||||||
|
|
||||||
|
// render side growth
|
||||||
|
ForgeDirection drawDirection = cactusDirections[getSemiRandomFromPos(x, y, z, 0) % 4];
|
||||||
|
int iconVariation = getSemiRandomFromPos(x, y, z, 1);
|
||||||
|
Double3 drawBase = blockCenter.add(new Double3(drawDirection).scale(cactusRadius));
|
||||||
|
|
||||||
|
Tessellator.instance.setBrightness(getBrightness(block, x, y, z));
|
||||||
|
if (cactusSideIcons.hasIcons()) renderCrossedSideQuads(drawBase, drawDirection, 0.5, 0.5, pRot[iconVariation], 0.2, cactusSideIcons.get(iconVariation), 0, false);
|
||||||
|
renderCrossedBlockQuadsSkew(blockCenter, 0.65,
|
||||||
|
pRot[iconVariation].scaleAxes(0.1, 0.0, 0.1),
|
||||||
|
pRot[(iconVariation + 1) & 63].scaleAxes(0.1, 0.0, 0.1),
|
||||||
|
cactusRoundIcon, iconVariation, false, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderCactusCore(IIcon topIcon, IIcon sideIcon, Double3 blockCenter, int sideUvRot) {
|
||||||
|
if (Minecraft.isAmbientOcclusionEnabled()) {
|
||||||
|
renderQuadWithShading(sideIcon, blockCenter.add(cactusRadius, 0.0, 0.0), new Double3(0.0, 0.0, -0.5), new Double3(0.0, 0.5, 0.0), sideUvRot, aoXPYZPN, aoXPYZPP, aoXPYZNP, aoXPYZNN);
|
||||||
|
renderQuadWithShading(sideIcon, blockCenter.add(-cactusRadius, 0.0, 0.0), new Double3(0.0, 0.0, 0.5), new Double3(0.0, 0.5, 0.0), sideUvRot, aoXNYZPP, aoXNYZPN, aoXNYZNN, aoXNYZNP);
|
||||||
|
renderQuadWithShading(sideIcon, blockCenter.add(0.0, 0.0, cactusRadius), new Double3(0.5, 0.0, 0.0), new Double3(0.0, 0.5, 0.0), sideUvRot, aoZPXYPP, aoZPXYNP, aoZPXYNN, aoZPXYPN);
|
||||||
|
renderQuadWithShading(sideIcon, blockCenter.add(0.0, 0.0, -cactusRadius), new Double3(-0.5, 0.0, 0.0), new Double3(0.0, 0.5, 0.0), sideUvRot, aoZNXYNP, aoZNXYPP, aoZNXYPN, aoZNXYNN);
|
||||||
|
renderQuadWithShading(topIcon, blockCenter.add(0.0, 0.5, 0.0), new Double3(-0.5, 0.0, 0.0), new Double3(0.0, 0.0, 0.5), 0, aoYPXZNP, aoYPXZPP, aoYPXZPN, aoYPXZNN);
|
||||||
|
} else {
|
||||||
|
renderQuad(sideIcon, blockCenter.add(cactusRadius, 0.0, 0.0), new Double3(0.0, 0.0, -0.5), new Double3(0.0, 0.5, 0.0), sideUvRot);
|
||||||
|
renderQuad(sideIcon, blockCenter.add(-cactusRadius, 0.0, 0.0), new Double3(0.0, 0.0, 0.5), new Double3(0.0, 0.5, 0.0), sideUvRot);
|
||||||
|
renderQuad(sideIcon, blockCenter.add(0.0, 0.0, cactusRadius), new Double3(0.5, 0.0, 0.0), new Double3(0.0, 0.5, 0.0), sideUvRot);
|
||||||
|
renderQuad(sideIcon, blockCenter.add(0.0, 0.0, -cactusRadius), new Double3(-0.5, 0.0, 0.0), new Double3(0.0, 0.5, 0.0), sideUvRot);
|
||||||
|
renderQuad(topIcon, blockCenter.add(0.0, 0.5, 0.0), new Double3(-0.5, 0.0, 0.0), new Double3(0.0, 0.0, 0.5), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleTextureReload(TextureStitchEvent.Pre event) {
|
||||||
|
if (event.map.getTextureType() != 0) return;
|
||||||
|
|
||||||
|
cactusRoundIcon = event.map.registerIcon("bettergrassandleaves:better_cactus");
|
||||||
|
cactusSideIcons.registerIcons(event.map);
|
||||||
|
BetterFoliage.log.info(String.format("Found %d cactus arm textures", cactusSideIcons.numLoaded));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package mods.betterfoliage.client.render.impl;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
||||||
|
import mods.betterfoliage.client.render.IconSet;
|
||||||
|
import mods.betterfoliage.client.render.RenderBlockAOBase;
|
||||||
|
import mods.betterfoliage.common.util.Double3;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.material.Material;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.util.MathHelper;
|
||||||
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
import net.minecraft.world.gen.NoiseGeneratorSimplex;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
|
||||||
|
public class RenderBlockBetterCoral extends RenderBlockAOBase implements IRenderBlockDecorator {
|
||||||
|
|
||||||
|
public IconSet coralCrustIcons = new IconSet("bettergrassandleaves", "better_crust_%d");
|
||||||
|
public IconSet coralCrossIcons = new IconSet("bettergrassandleaves", "better_coral_%d");
|
||||||
|
public NoiseGeneratorSimplex noise;
|
||||||
|
|
||||||
|
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
|
||||||
|
if (!BetterFoliage.config.coralEnabled) return false;
|
||||||
|
if (block != Blocks.sand) return false;
|
||||||
|
int terrainVariation = MathHelper.floor_double((noise.func_151605_a(x * 0.1, z * 0.1) + 1.0) * 32.0);
|
||||||
|
return terrainVariation < BetterFoliage.config.coralPopulation.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
|
||||||
|
// store world for later use
|
||||||
|
blockAccess = world;
|
||||||
|
|
||||||
|
// render sand block
|
||||||
|
setPassCounters(1);
|
||||||
|
setRenderBoundsFromBlock(block);
|
||||||
|
renderStandardBlock(block, x, y, z);
|
||||||
|
|
||||||
|
Double3 blockCenter = new Double3(x + 0.5, y + 0.5, z + 0.5);
|
||||||
|
double offset = pRand[getSemiRandomFromPos(x, y, z, 6)] * BetterFoliage.config.coralVOffset.value;
|
||||||
|
double halfSize = BetterFoliage.config.coralSize.value * 0.5;
|
||||||
|
double halfCrustSize = BetterFoliage.config.coralCrustSize.value * 0.5;
|
||||||
|
|
||||||
|
Tessellator.instance.setBrightness(getBrightness(block, x, y, z));
|
||||||
|
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
|
||||||
|
if (blockAccess.getBlock(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ).getMaterial() != Material.water) continue;
|
||||||
|
if (blockAccess.isAirBlock(x + dir.offsetX, y + dir.offsetY + 1, z + dir.offsetZ)) continue;
|
||||||
|
|
||||||
|
int variation = getSemiRandomFromPos(x, y, z, dir.ordinal());
|
||||||
|
if (variation < BetterFoliage.config.coralChance.value) {
|
||||||
|
IIcon crustIcon = coralCrustIcons.get(variation);
|
||||||
|
IIcon coralIcon = coralCrossIcons.get(variation);
|
||||||
|
if (crustIcon != null) renderCoralCrust(blockCenter, dir, offset, halfCrustSize, crustIcon, variation);
|
||||||
|
if (coralIcon != null) renderCrossedSideQuads(blockCenter.add(new Double3(dir).scale(0.5)), dir,
|
||||||
|
halfSize, halfSize,
|
||||||
|
pRot[variation], BetterFoliage.config.coralHOffset.value,
|
||||||
|
coralIcon, 0, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderCoralCrust(Double3 blockCenter, ForgeDirection dir, double offset, double scale, IIcon icon, int uvRot) {
|
||||||
|
Double3 face1 = new Double3(faceDir1[dir.ordinal()]).scale(scale);
|
||||||
|
Double3 face2 = new Double3(faceDir2[dir.ordinal()]).scale(scale);
|
||||||
|
Double3 drawCenter = blockCenter.add(new Double3(dir).scale(0.5 + offset));
|
||||||
|
if (Minecraft.isAmbientOcclusionEnabled()) {
|
||||||
|
setShadingForFace(dir);
|
||||||
|
renderQuadWithShading(icon, drawCenter, face1, face2, uvRot, faceAOPP, faceAONP, faceAONN, faceAOPN);
|
||||||
|
} else {
|
||||||
|
renderQuad(icon, drawCenter, face1, face2, uvRot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleTextureReload(TextureStitchEvent.Pre event) {
|
||||||
|
if (event.map.getTextureType() != 0) return;
|
||||||
|
|
||||||
|
coralCrustIcons.registerIcons(event.map);
|
||||||
|
coralCrossIcons.registerIcons(event.map);
|
||||||
|
BetterFoliage.log.info(String.format("Found %d coral crust textures", coralCrustIcons.numLoaded));
|
||||||
|
BetterFoliage.log.info(String.format("Found %d coral textures", coralCrossIcons.numLoaded));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleWorldLoad(WorldEvent.Load event) {
|
||||||
|
noise = new NoiseGeneratorSimplex(new Random(event.world.getWorldInfo().getSeed() + 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package mods.betterfoliage.client.render.impl;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.ShadersModIntegration;
|
||||||
|
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
||||||
|
import mods.betterfoliage.client.render.IconSet;
|
||||||
|
import mods.betterfoliage.client.render.RenderBlockAOBase;
|
||||||
|
import mods.betterfoliage.common.util.Double3;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockGrass;
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class RenderBlockBetterGrass extends RenderBlockAOBase implements IRenderBlockDecorator {
|
||||||
|
|
||||||
|
public IconSet grassIcons = new IconSet("bettergrassandleaves", "better_grass_long_%d");
|
||||||
|
public IconSet snowGrassIcons = new IconSet("bettergrassandleaves", "better_grass_snowed_%d");
|
||||||
|
public IconSet myceliumIcons = new IconSet("bettergrassandleaves", "better_mycel_%d");
|
||||||
|
public IIcon grassGenIcon;
|
||||||
|
public IIcon snowGrassGenIcon;
|
||||||
|
|
||||||
|
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
|
||||||
|
if (!BetterFoliage.config.grassEnabled) return false;
|
||||||
|
if (!((block instanceof BlockGrass || block == Blocks.mycelium))) return false;
|
||||||
|
if (!blockAccess.isAirBlock(x, y + 1, z) && blockAccess.getBlock(x, y + 1, z) != Blocks.snow_layer) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
|
||||||
|
// store world for later use
|
||||||
|
blockAccess = world;
|
||||||
|
|
||||||
|
// render grass block
|
||||||
|
setPassCounters(1);
|
||||||
|
setRenderBoundsFromBlock(block);
|
||||||
|
renderStandardBlock(block, x, y, z);
|
||||||
|
|
||||||
|
int variation = getSemiRandomFromPos(x, y, z, 0);
|
||||||
|
int heightVariation = getSemiRandomFromPos(x, y, z, 1);
|
||||||
|
boolean isSnowed = blockAccess.getBlock(x, y + 1, z) == Blocks.snow_layer;
|
||||||
|
|
||||||
|
IIcon renderIcon = null;
|
||||||
|
if (block instanceof BlockGrass) {
|
||||||
|
if (BetterFoliage.config.grassUseGenerated) {
|
||||||
|
renderIcon = isSnowed ? snowGrassGenIcon : grassGenIcon;
|
||||||
|
} else {
|
||||||
|
renderIcon = isSnowed ? snowGrassIcons.get(variation) : grassIcons.get(variation);
|
||||||
|
}
|
||||||
|
} else if (block == Blocks.mycelium && !isSnowed) {
|
||||||
|
renderIcon = myceliumIcons.get(variation);
|
||||||
|
}
|
||||||
|
if (renderIcon == null) return true;
|
||||||
|
|
||||||
|
double scale = BetterFoliage.config.grassSize.value * 0.5;
|
||||||
|
double halfHeight = 0.5 * (BetterFoliage.config.grassHeightMin.value + pRand[heightVariation] * (BetterFoliage.config.grassHeightMax.value - BetterFoliage.config.grassHeightMin.value));
|
||||||
|
|
||||||
|
if (isSnowed) {
|
||||||
|
aoYPXZNN.setGray(0.9f); aoYPXZNP.setGray(0.9f); aoYPXZPN.setGray(0.9f); aoYPXZPP.setGray(0.9f);
|
||||||
|
Tessellator.instance.setColorOpaque(230, 230, 230);
|
||||||
|
}
|
||||||
|
|
||||||
|
// render short grass
|
||||||
|
ShadersModIntegration.startGrassQuads();
|
||||||
|
Tessellator.instance.setBrightness(getBrightness(block, x, y + 1, z));
|
||||||
|
renderCrossedSideQuads(new Double3(x + 0.5, y + 1.0 + (isSnowed ? 0.0625 : 0.0), z + 0.5), ForgeDirection.UP, scale, halfHeight, pRot[variation], BetterFoliage.config.grassHOffset.value, renderIcon, 0, false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleTextureReload(TextureStitchEvent.Pre event) {
|
||||||
|
if (event.map.getTextureType() != 0) return;
|
||||||
|
|
||||||
|
grassIcons.registerIcons(event.map);
|
||||||
|
snowGrassIcons.registerIcons(event.map);
|
||||||
|
myceliumIcons.registerIcons(event.map);
|
||||||
|
grassGenIcon = event.map.registerIcon("bf_shortgrass:minecraft:tallgrass");
|
||||||
|
snowGrassGenIcon = event.map.registerIcon("bf_shortgrass_snow:minecraft:tallgrass");
|
||||||
|
BetterFoliage.log.info(String.format("Found %d short grass textures", grassIcons.numLoaded));
|
||||||
|
BetterFoliage.log.info(String.format("Found %d snowy grass textures", snowGrassIcons.numLoaded));
|
||||||
|
BetterFoliage.log.info(String.format("Found %d mycelium textures", myceliumIcons.numLoaded));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package mods.betterfoliage.client.render.impl;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.BetterFoliageClient;
|
||||||
|
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
||||||
|
import mods.betterfoliage.client.render.RenderBlockAOBase;
|
||||||
|
import mods.betterfoliage.common.util.Double3;
|
||||||
|
import mods.betterfoliage.common.util.Utils;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class RenderBlockBetterLeaves extends RenderBlockAOBase implements IRenderBlockDecorator {
|
||||||
|
|
||||||
|
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
|
||||||
|
if (!BetterFoliage.config.leavesEnabled) return false;
|
||||||
|
if (original > 0 && original < 42) return false;
|
||||||
|
return BetterFoliageClient.leaves.matchesID(block) && !isBlockSurrounded(blockAccess, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
|
||||||
|
// store world for later use
|
||||||
|
blockAccess = world;
|
||||||
|
|
||||||
|
// render leaves center
|
||||||
|
setPassCounters(1);
|
||||||
|
setRenderBoundsFromBlock(block);
|
||||||
|
if (block.getRenderType() == 0) {
|
||||||
|
renderStandardBlock(block, x, y, z);
|
||||||
|
} else {
|
||||||
|
ISimpleBlockRenderingHandler handler = Utils.getRenderingHandler(block.getRenderType());
|
||||||
|
handler.renderWorldBlock(world, x, y, z, block, block.getRenderType(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find generated texture to render with, assume the
|
||||||
|
// "true" texture of the block is the one on the north size
|
||||||
|
TextureAtlasSprite blockLeafIcon = (TextureAtlasSprite) block.getIcon(world, x, y, z, ForgeDirection.NORTH.ordinal());
|
||||||
|
if (blockLeafIcon == null) {
|
||||||
|
BetterFoliage.log.debug(String.format("null leaf texture, x:%d, y:%d, z:%d, meta:%d, block:%s", x, y, z, blockAccess.getBlockMetadata(x, y, z), block.getClass().getName()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
IIcon crossLeafIcon = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(BetterFoliageClient.leafGenerator.domainName + ":" + blockLeafIcon.getIconName());
|
||||||
|
if (crossLeafIcon == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int offsetVariation = getSemiRandomFromPos(x, y, z, 0);
|
||||||
|
int uvVariation = getSemiRandomFromPos(x, y, z, 1);
|
||||||
|
double halfSize = 0.5 * BetterFoliage.config.leavesSize.value;
|
||||||
|
boolean isAirTop = y == 255 || blockAccess.isAirBlock(x, y + 1, z);
|
||||||
|
boolean isAirBottom = y == 0 || blockAccess.isAirBlock(x, y - 1, z);
|
||||||
|
|
||||||
|
Tessellator.instance.setBrightness(isAirTop ? getBrightness(block, x, y + 1, z) : (isAirBottom ? getBrightness(block, x, y - 1, z) : getBrightness(block, x, y, z)));
|
||||||
|
Tessellator.instance.setColorOpaque_I(block.colorMultiplier(blockAccess, x, y, z));
|
||||||
|
|
||||||
|
if (BetterFoliage.config.leavesSkew) {
|
||||||
|
renderCrossedBlockQuadsSkew(new Double3(x + 0.5, y + 0.5, z + 0.5), halfSize,
|
||||||
|
pRot[offsetVariation].scaleAxes(BetterFoliage.config.leavesHOffset.value, BetterFoliage.config.leavesVOffset.value, BetterFoliage.config.leavesHOffset.value),
|
||||||
|
pRot[(offsetVariation + 1) & 63].scaleAxes(BetterFoliage.config.leavesHOffset.value, BetterFoliage.config.leavesVOffset.value, BetterFoliage.config.leavesHOffset.value),
|
||||||
|
crossLeafIcon, uvVariation, isAirTop, isAirBottom);
|
||||||
|
} else {
|
||||||
|
renderCrossedBlockQuadsTranslate(new Double3(x + 0.5, y + 0.5, z + 0.5), halfSize,
|
||||||
|
pRot[offsetVariation].scaleAxes(BetterFoliage.config.leavesHOffset.value, BetterFoliage.config.leavesVOffset.value, BetterFoliage.config.leavesHOffset.value),
|
||||||
|
crossLeafIcon, uvVariation, isAirTop, isAirBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isBlockSurrounded(IBlockAccess blockAccess, int x, int y, int z) {
|
||||||
|
if (blockAccess.isAirBlock(x + 1, y, z)) return false;
|
||||||
|
if (blockAccess.isAirBlock(x - 1, y, z)) return false;
|
||||||
|
if (blockAccess.isAirBlock(x, y, z + 1)) return false;
|
||||||
|
if (blockAccess.isAirBlock(x, y, z - 1)) return false;
|
||||||
|
if (y == 255 || blockAccess.isAirBlock(x, y + 1, z)) return false;
|
||||||
|
if (y == 0 || blockAccess.isAirBlock(x, y - 1, z)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package mods.betterfoliage.client.render.impl;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.render.FakeRenderBlockAOBase;
|
||||||
|
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
||||||
|
import mods.betterfoliage.client.render.IconSet;
|
||||||
|
import mods.betterfoliage.common.util.Double3;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class RenderBlockBetterLilypad extends FakeRenderBlockAOBase implements IRenderBlockDecorator {
|
||||||
|
|
||||||
|
public IconSet lilypadFlowers = new IconSet("bettergrassandleaves", "better_lilypad_flower_%d");
|
||||||
|
public IconSet lilypadRoots = new IconSet("bettergrassandleaves", "better_lilypad_roots_%d");
|
||||||
|
|
||||||
|
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
|
||||||
|
return BetterFoliage.config.lilypadEnabled && block == Blocks.waterlily;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
|
||||||
|
// store world for later use
|
||||||
|
blockAccess = world;
|
||||||
|
|
||||||
|
// render lilypad block
|
||||||
|
renderBlockLilyPad(block, x, y, z);
|
||||||
|
|
||||||
|
int chanceVariation = getSemiRandomFromPos(x, y, z, 0);
|
||||||
|
int iconVariation = getSemiRandomFromPos(x, y, z, 1);
|
||||||
|
int offsetVariation = getSemiRandomFromPos(x, y, z, 2);
|
||||||
|
|
||||||
|
Tessellator.instance.setBrightness(getBrightness(block, x, y, z));
|
||||||
|
Tessellator.instance.setColorOpaque(255, 255, 255);
|
||||||
|
if (lilypadRoots.hasIcons()) renderCrossedSideQuads(new Double3(x + 0.5, y + 0.015, z + 0.5), ForgeDirection.DOWN,
|
||||||
|
0.2, 0.3,
|
||||||
|
null, 0.0,
|
||||||
|
lilypadRoots.get(iconVariation), 2,
|
||||||
|
true);
|
||||||
|
if (chanceVariation < BetterFoliage.config.lilypadChance.value && lilypadFlowers.hasIcons())
|
||||||
|
renderCrossedSideQuads(new Double3(x + 0.5, y + 0.02, z + 0.5), ForgeDirection.UP,
|
||||||
|
0.2, 0.3,
|
||||||
|
pRot[offsetVariation], BetterFoliage.config.lilypadHOffset.value,
|
||||||
|
lilypadFlowers.get(iconVariation), 0,
|
||||||
|
true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleTextureReload(TextureStitchEvent.Pre event) {
|
||||||
|
if (event.map.getTextureType() != 0) return;
|
||||||
|
|
||||||
|
lilypadFlowers.registerIcons(event.map);
|
||||||
|
lilypadRoots.registerIcons(event.map);
|
||||||
|
BetterFoliage.log.info(String.format("Found %d lilypad flower textures", lilypadFlowers.numLoaded));
|
||||||
|
BetterFoliage.log.info(String.format("Found %d lilypad root textures", lilypadRoots.numLoaded));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package mods.betterfoliage.client.render.impl;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.ShadersModIntegration;
|
||||||
|
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
||||||
|
import mods.betterfoliage.client.render.IconSet;
|
||||||
|
import mods.betterfoliage.client.render.RenderBlockAOBase;
|
||||||
|
import mods.betterfoliage.common.util.Double3;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockDirt;
|
||||||
|
import net.minecraft.block.material.Material;
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.util.MathHelper;
|
||||||
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
import net.minecraft.world.gen.NoiseGeneratorSimplex;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class RenderBlockBetterReed extends RenderBlockAOBase implements IRenderBlockDecorator {
|
||||||
|
|
||||||
|
public IconSet reedBottomIcons = new IconSet("bf_reed_bottom", "bettergrassandleaves:better_reed_%d");
|
||||||
|
public IconSet reedTopIcons = new IconSet("bf_reed_top", "bettergrassandleaves:better_reed_%d");
|
||||||
|
public NoiseGeneratorSimplex noise;
|
||||||
|
|
||||||
|
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
|
||||||
|
if (!BetterFoliage.config.reedEnabled) return false;
|
||||||
|
if (y >= 254 || !(block instanceof BlockDirt)) return false;
|
||||||
|
if (blockAccess.getBlock(x, y + 1, z).getMaterial() != Material.water) return false;
|
||||||
|
if (!blockAccess.isAirBlock(x, y + 2, z)) return false;
|
||||||
|
if (blockAccess.getBiomeGenForCoords(x, z).temperature < 0.4f || blockAccess.getBiomeGenForCoords(x, z).rainfall < 0.4f) return false;
|
||||||
|
int terrainVariation = MathHelper.floor_double((noise.func_151605_a(x, z) + 1.0) * 32.0);
|
||||||
|
return terrainVariation < BetterFoliage.config.reedChance.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
|
||||||
|
// store world for later use
|
||||||
|
blockAccess = world;
|
||||||
|
|
||||||
|
// render dirt block
|
||||||
|
setPassCounters(1);
|
||||||
|
setRenderBoundsFromBlock(block);
|
||||||
|
renderStandardBlock(block, x, y, z);
|
||||||
|
|
||||||
|
int iconVariation = getSemiRandomFromPos(x, y, z, 0);
|
||||||
|
int heightVariation = getSemiRandomFromPos(x, y, z, 1);
|
||||||
|
|
||||||
|
IIcon bottomIcon = reedBottomIcons.get(iconVariation);
|
||||||
|
IIcon topIcon = reedTopIcons.get(iconVariation);
|
||||||
|
if (bottomIcon == null || topIcon == null) return true;
|
||||||
|
|
||||||
|
double quarterHeight = 0.25 * (BetterFoliage.config.reedHeightMin.value + pRand[heightVariation] * (BetterFoliage.config.reedHeightMax.value - BetterFoliage.config.reedHeightMin.value));
|
||||||
|
Tessellator.instance.setBrightness(getBrightness(block, x, y + 2, z));
|
||||||
|
Tessellator.instance.setColorOpaque(255, 255, 255);
|
||||||
|
|
||||||
|
// render reeds
|
||||||
|
ShadersModIntegration.startGrassQuads();
|
||||||
|
renderCrossedSideQuads(new Double3(x + 0.5, y + 1.0, z + 0.5), ForgeDirection.UP, 0.5, quarterHeight, pRot[iconVariation], BetterFoliage.config.reedHOffset.value, bottomIcon, 0, true);
|
||||||
|
renderCrossedSideQuads(new Double3(x + 0.5, y + 1.0 + 2.0 * quarterHeight, z + 0.5), ForgeDirection.UP, 0.5, quarterHeight, pRot[iconVariation], BetterFoliage.config.reedHOffset.value, topIcon, 0, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleTextureReload(TextureStitchEvent.Pre event) {
|
||||||
|
if (event.map.getTextureType() != 0) return;
|
||||||
|
|
||||||
|
reedBottomIcons.registerIcons(event.map);
|
||||||
|
reedTopIcons.registerIcons(event.map);
|
||||||
|
BetterFoliage.log.info(String.format("Found %d reed textures", reedBottomIcons.numLoaded));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleWorldLoad(WorldEvent.Load event) {
|
||||||
|
noise = new NoiseGeneratorSimplex(new Random(event.world.getWorldInfo().getSeed()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package mods.betterfoliage.client.resource;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.common.util.Utils;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureMap;
|
||||||
|
import net.minecraft.client.resources.IResource;
|
||||||
|
import net.minecraft.client.resources.IResourceManager;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public abstract class BlockTextureGenerator implements IResourceManager {
|
||||||
|
|
||||||
|
/** Resource domain name of generated textures */
|
||||||
|
public String domainName;
|
||||||
|
|
||||||
|
/** Resource location for fallback texture (if the generation process fails) */
|
||||||
|
public ResourceLocation missingResource;
|
||||||
|
|
||||||
|
/** Texture atlas for block textures used in the current run */
|
||||||
|
public TextureMap blockTextures;
|
||||||
|
|
||||||
|
/** Number of textures generated in the current run */
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
public BlockTextureGenerator(String domainName, ResourceLocation missingResource) {
|
||||||
|
this.domainName = domainName;
|
||||||
|
this.missingResource = missingResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onStitchStart(TextureStitchEvent.Pre event) {}
|
||||||
|
|
||||||
|
public void onStitchEnd(TextureStitchEvent.Post event) {}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleTextureReload(TextureStitchEvent.Pre event) {
|
||||||
|
if (event.map.getTextureType() != 0) return;
|
||||||
|
|
||||||
|
blockTextures = event.map;
|
||||||
|
counter = 0;
|
||||||
|
Map<String, IResourceManager> domainManagers = Utils.getDomainResourceManagers();
|
||||||
|
if (domainManagers == null) {
|
||||||
|
BetterFoliage.log.warn("Failed to inject texture generator");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
domainManagers.put(domainName, this);
|
||||||
|
|
||||||
|
onStitchStart(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void endTextureReload(TextureStitchEvent.Post event) {
|
||||||
|
blockTextures = null;
|
||||||
|
if (event.map.getTextureType() != 0) return;
|
||||||
|
|
||||||
|
// don't leave a mess
|
||||||
|
Map<String, IResourceManager> domainManagers = Utils.getDomainResourceManagers();
|
||||||
|
if (domainManagers != null) domainManagers.remove(domainName);
|
||||||
|
|
||||||
|
onStitchEnd(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getResourceDomains() {
|
||||||
|
return ImmutableSet.<String>of(domainName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IResource> getAllResources(ResourceLocation resource) throws IOException {
|
||||||
|
return ImmutableList.<IResource>of(getResource(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IResource getMissingResource() throws IOException {
|
||||||
|
return Minecraft.getMinecraft().getResourceManager().getResource(missingResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceLocation unwrapResource(ResourceLocation wrapped) {
|
||||||
|
return new ResourceLocation(wrapped.getResourcePath().substring(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package mods.betterfoliage.client.resource;
|
||||||
|
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.resources.IResource;
|
||||||
|
import net.minecraft.client.resources.IResourceManager;
|
||||||
|
import net.minecraft.client.resources.data.IMetadataSection;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
/** {@link IResource} of PNG containing one half (top or bottom) of a given texture resource
|
||||||
|
* @author octarine-noise
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class HalfTextureResource implements IResource {
|
||||||
|
|
||||||
|
/** Raw PNG data*/
|
||||||
|
public byte[] data = null;
|
||||||
|
|
||||||
|
/** Resource to return if generation fails */
|
||||||
|
public IResource fallbackResource;
|
||||||
|
|
||||||
|
public HalfTextureResource(ResourceLocation resource, boolean bottom, IResource fallbackResource) {
|
||||||
|
this.fallbackResource = fallbackResource;
|
||||||
|
|
||||||
|
IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager();
|
||||||
|
try {
|
||||||
|
// load full texture
|
||||||
|
ResourceLocation origResource = new ResourceLocation(resource.getResourceDomain(), "textures/blocks/" + resource.getResourcePath());
|
||||||
|
BufferedImage origImage = ImageIO.read(resourceManager.getResource(origResource).getInputStream());
|
||||||
|
|
||||||
|
// draw half texture
|
||||||
|
BufferedImage result = new BufferedImage(origImage.getWidth(), origImage.getHeight() / 2, BufferedImage.TYPE_4BYTE_ABGR);
|
||||||
|
Graphics2D graphics = result.createGraphics();
|
||||||
|
graphics.drawImage(origImage, 0, bottom ? -origImage.getHeight() / 2 : 0, null);
|
||||||
|
|
||||||
|
// create PNG image
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ImageIO.write(result, "PNG", baos);
|
||||||
|
data = baos.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// stop log spam with GLSL installed
|
||||||
|
if (e instanceof FileNotFoundException) return;
|
||||||
|
BetterFoliage.log.info(String.format("Could not load texture: %s, exception: %s", resource.toString(), e.getClass().getSimpleName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
return data != null ? new ByteArrayInputStream(data) : fallbackResource.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasMetadata() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IMetadataSection getMetadata(String var1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package mods.betterfoliage.client.resource;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import mods.betterfoliage.client.BetterFoliageClient;
|
||||||
|
import mods.betterfoliage.common.util.Utils;
|
||||||
|
import mods.betterfoliage.loader.DeobfHelper;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.client.resources.IResource;
|
||||||
|
import net.minecraft.client.resources.IResourceManager;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent.Post;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent.Pre;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
/** Generates rounded crossleaf textures for all registered normal leaf textures at stitch time.
|
||||||
|
* @author octarine-noise
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class LeafTextureGenerator extends BlockTextureGenerator implements IIconRegister {
|
||||||
|
|
||||||
|
public String nonGeneratedDomain = "betterfoliage";
|
||||||
|
|
||||||
|
public int nonGeneratedCounter = 0;
|
||||||
|
|
||||||
|
public LeafTextureGenerator() {
|
||||||
|
super("bf_leaves_autogen", new ResourceLocation("betterfoliage", "textures/blocks/missing_leaf.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IResource getResource(ResourceLocation resourceLocation) throws IOException {
|
||||||
|
IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager();
|
||||||
|
ResourceLocation originalNoDirs = unwrapResource(resourceLocation);
|
||||||
|
ResourceLocation originalWithDirs = new ResourceLocation(originalNoDirs.getResourceDomain(), "textures/blocks/" + originalNoDirs.getResourcePath());
|
||||||
|
|
||||||
|
// check for provided texture
|
||||||
|
ResourceLocation handDrawnLocation = new ResourceLocation(nonGeneratedDomain, String.format("textures/blocks/%s/%s", originalNoDirs.getResourceDomain(), originalNoDirs.getResourcePath()));
|
||||||
|
if (Utils.resourceExists(handDrawnLocation)) {
|
||||||
|
nonGeneratedCounter++;
|
||||||
|
return resourceManager.getResource(handDrawnLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't alter ShaderMod normal and specular maps
|
||||||
|
if (originalWithDirs.getResourcePath().toLowerCase().endsWith("_n.png") || originalWithDirs.getResourcePath().toLowerCase().endsWith("_s.png")) {
|
||||||
|
resourceManager.getResource(originalWithDirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate our own
|
||||||
|
if (!Utils.resourceExists(originalWithDirs)) return getMissingResource();
|
||||||
|
LeafTextureResource result = new LeafTextureResource(resourceManager.getResource(originalWithDirs));
|
||||||
|
if (result.data != null) {
|
||||||
|
counter++;
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return getMissingResource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Leaf blocks register their textures here. An extra texture will be registered in the atlas
|
||||||
|
* for each, with the resource domain of this generator.
|
||||||
|
* @return the originally registered {@link IIcon} already in the atlas
|
||||||
|
*/
|
||||||
|
public IIcon registerIcon(String resourceLocation) {
|
||||||
|
IIcon original = blockTextures.getTextureExtry(resourceLocation);
|
||||||
|
blockTextures.registerIcon(new ResourceLocation(domainName, resourceLocation).toString());
|
||||||
|
BetterFoliage.log.debug(String.format("Found leaf texture: %s", resourceLocation));
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Iterates through all leaf blocks in the registry and makes them register
|
||||||
|
* their textures to "sniff out" all leaf textures.
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void onStitchStart(Pre event) {
|
||||||
|
nonGeneratedCounter = 0;
|
||||||
|
BetterFoliage.log.info("Reloading leaf textures");
|
||||||
|
|
||||||
|
// register simple block textures
|
||||||
|
Iterator<Block> iter = Block.blockRegistry.iterator();
|
||||||
|
while(iter.hasNext()) {
|
||||||
|
Block block = iter.next();
|
||||||
|
if (BetterFoliageClient.leaves.matchesClass(block)) {
|
||||||
|
BetterFoliage.log.debug(String.format("Inspecting leaf block: %s", block.getClass().getName()));
|
||||||
|
block.registerBlockIcons(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// enumerate all registered textures, find leaf textures among them
|
||||||
|
Map<String, TextureAtlasSprite> mapAtlas = null;
|
||||||
|
mapAtlas = Utils.getField(blockTextures, DeobfHelper.transformElementSearge("mapRegisteredSprites"), Map.class);
|
||||||
|
if (mapAtlas == null) mapAtlas = Utils.getField(blockTextures, "mapRegisteredSprites", Map.class);
|
||||||
|
if (mapAtlas == null) {
|
||||||
|
BetterFoliage.log.warn("Failed to reflect texture atlas, textures may be missing");
|
||||||
|
} else {
|
||||||
|
Set<String> foundLeafTextures = Sets.newHashSet();
|
||||||
|
for (TextureAtlasSprite icon : mapAtlas.values())
|
||||||
|
if (BetterFoliageClient.isLeafTexture(icon))
|
||||||
|
foundLeafTextures.add(icon.getIconName());
|
||||||
|
for (String resourceLocation : foundLeafTextures) {
|
||||||
|
BetterFoliage.log.debug(String.format("Found non-block-registered leaf texture: %s", resourceLocation));
|
||||||
|
blockTextures.registerIcon(new ResourceLocation(domainName, resourceLocation).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStitchEnd(Post event) {
|
||||||
|
BetterFoliage.log.info(String.format("Found %d pre-drawn leaf textures", nonGeneratedCounter));
|
||||||
|
BetterFoliage.log.info(String.format("Generated %d leaf textures", counter));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package mods.betterfoliage.client.resource;
|
||||||
|
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.resources.IResource;
|
||||||
|
import net.minecraft.client.resources.IResourceManager;
|
||||||
|
import net.minecraft.client.resources.data.IMetadataSection;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
/** {@link IResource} containing an autogenerated round crossleaf texture
|
||||||
|
* @author octarine-noise
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class LeafTextureResource implements IResource {
|
||||||
|
|
||||||
|
/** Raw PNG data*/
|
||||||
|
protected byte[] data = null;
|
||||||
|
|
||||||
|
/** Name of the default alpha mask to use */
|
||||||
|
public static String defaultMask = "rough";
|
||||||
|
|
||||||
|
public LeafTextureResource(IResource resLeaf) {
|
||||||
|
try {
|
||||||
|
// load normal leaf texture
|
||||||
|
BufferedImage origImage = ImageIO.read(resLeaf.getInputStream());
|
||||||
|
if (origImage.getWidth() != origImage.getHeight()) return;
|
||||||
|
int size = origImage.getWidth();
|
||||||
|
|
||||||
|
// load alpha mask of appropriate size
|
||||||
|
BufferedImage maskImage = loadLeafMaskImage(defaultMask, size * 2);
|
||||||
|
int scale = size * 2 / maskImage.getWidth();
|
||||||
|
|
||||||
|
// tile leaf texture 2x2
|
||||||
|
BufferedImage overlayIcon = new BufferedImage(size * 2, size * 2, BufferedImage.TYPE_4BYTE_ABGR);
|
||||||
|
Graphics2D graphics = overlayIcon.createGraphics();
|
||||||
|
graphics.drawImage(origImage, 0, 0, null);
|
||||||
|
graphics.drawImage(origImage, 0, size, null);
|
||||||
|
graphics.drawImage(origImage, size, 0, null);
|
||||||
|
graphics.drawImage(origImage, size, size, null);
|
||||||
|
|
||||||
|
// overlay mask alpha on texture
|
||||||
|
for (int x = 0; x < overlayIcon.getWidth(); x++) {
|
||||||
|
for (int y = 0; y < overlayIcon.getHeight(); y++) {
|
||||||
|
long origPixel = overlayIcon.getRGB(x, y) & 0xFFFFFFFFl;
|
||||||
|
long maskPixel = maskImage.getRGB(x / scale, y / scale) & 0xFF000000l | 0x00FFFFFF;
|
||||||
|
overlayIcon.setRGB(x, y, (int) (origPixel & maskPixel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create PNG image
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ImageIO.write(overlayIcon, "PNG", baos);
|
||||||
|
data = baos.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// stop log spam with GLSL installed
|
||||||
|
BetterFoliage.log.info(String.format("Could not create leaf texture: %s, exception: %s", resLeaf.toString(), e.getClass().getSimpleName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Loads the alpha mask of the given type and size. If a mask of the exact size can not be found,
|
||||||
|
* will try to load progressively smaller masks down to 16x16
|
||||||
|
* @param type mask type
|
||||||
|
* @param size texture size
|
||||||
|
* @return alpha mask
|
||||||
|
*/
|
||||||
|
protected BufferedImage loadLeafMaskImage(String type, int size) {
|
||||||
|
IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager();
|
||||||
|
IResource maskResource = null;
|
||||||
|
|
||||||
|
while (maskResource == null && size >= 16) {
|
||||||
|
try {
|
||||||
|
maskResource = resourceManager.getResource(new ResourceLocation(String.format("betterfoliage:textures/blocks/leafmask_%d_%s.png", size, type)));
|
||||||
|
} catch (Exception e) {}
|
||||||
|
size /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return maskResource == null ? null : ImageIO.read(maskResource.getInputStream());
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
return new ByteArrayInputStream(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasMetadata() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMetadataSection getMetadata(String var1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package mods.betterfoliage.client.resource;
|
||||||
|
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import mods.betterfoliage.BetterFoliage;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.resources.IResource;
|
||||||
|
import net.minecraft.client.resources.IResourceManager;
|
||||||
|
import net.minecraft.client.resources.data.IMetadataSection;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
public class ShortGrassTextureResource implements IResource {
|
||||||
|
|
||||||
|
/** Raw PNG data*/
|
||||||
|
public byte[] data = null;
|
||||||
|
|
||||||
|
/** Resource to return if generation fails */
|
||||||
|
public IResource fallbackResource;
|
||||||
|
|
||||||
|
public ShortGrassTextureResource(ResourceLocation resource, boolean isSnowed, IResource fallbackResource) {
|
||||||
|
this.fallbackResource = fallbackResource;
|
||||||
|
boolean isSpecialTexture = resource.getResourcePath().toLowerCase().endsWith("_n.png") || resource.getResourcePath().toLowerCase().endsWith("_s.png");
|
||||||
|
|
||||||
|
IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager();
|
||||||
|
try {
|
||||||
|
// load full texture
|
||||||
|
ResourceLocation origResource = new ResourceLocation(resource.getResourceDomain(), "textures/blocks/" + resource.getResourcePath());
|
||||||
|
BufferedImage origImage = ImageIO.read(resourceManager.getResource(origResource).getInputStream());
|
||||||
|
|
||||||
|
// draw bottom half of texture
|
||||||
|
BufferedImage result = new BufferedImage(origImage.getWidth(), origImage.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
|
||||||
|
Graphics2D graphics = result.createGraphics();
|
||||||
|
graphics.drawImage(origImage, 0, 3 * origImage.getHeight() / 8, null);
|
||||||
|
|
||||||
|
// blend with white if snowed
|
||||||
|
if (isSnowed && !isSpecialTexture) {
|
||||||
|
for (int x = 0; x < result.getWidth(); x++) for (int y = 0; y < result.getHeight(); y++) {
|
||||||
|
result.setRGB(x, y, blend(result.getRGB(x, y), 0xFFFFFF, 2, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create PNG image
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ImageIO.write(result, "PNG", baos);
|
||||||
|
data = baos.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// stop log spam with GLSL installed
|
||||||
|
BetterFoliage.log.info(String.format("Could not load texture: %s, exception: %s", resource.toString(), e.getClass().getSimpleName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int blend(int rgbOrig, int rgbBlend, int weightOrig, int weightBlend) {
|
||||||
|
int r = ((rgbOrig & 0xFF) * weightOrig + (rgbBlend & 0xFF) * weightBlend) / (weightOrig + weightBlend);
|
||||||
|
int g = (((rgbOrig >> 8) & 0xFF) * weightOrig + ((rgbBlend >> 8) & 0xFF) * weightBlend) / (weightOrig + weightBlend);
|
||||||
|
int b = (((rgbOrig >> 16) & 0xFF) * weightOrig + ((rgbBlend >> 16) & 0xFF) * weightBlend) / (weightOrig + weightBlend);
|
||||||
|
int a = (rgbOrig >> 24) & 0xFF;
|
||||||
|
int result = (int) (a << 24 | b << 16 | g << 8 | r);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
return data != null ? new ByteArrayInputStream(data) : fallbackResource.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasMetadata() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IMetadataSection getMetadata(String var1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package mods.betterfoliage.common.config;
|
||||||
|
|
||||||
|
public class BetterFoliageConfig extends ConfigBase {
|
||||||
|
|
||||||
|
@CfgElement(category="leaves", key="enabled")
|
||||||
|
public boolean leavesEnabled = true;
|
||||||
|
|
||||||
|
@CfgElement(category="leaves", key="skewMode")
|
||||||
|
public boolean leavesSkew = false;
|
||||||
|
|
||||||
|
@CfgElement(category="grass", key="enabled")
|
||||||
|
public boolean grassEnabled = true;
|
||||||
|
|
||||||
|
@CfgElement(category="grass", key="useGenerated")
|
||||||
|
public boolean grassUseGenerated = false;
|
||||||
|
|
||||||
|
@CfgElement(category="cactus", key="enabled")
|
||||||
|
public boolean cactusEnabled = true;
|
||||||
|
|
||||||
|
@CfgElement(category="lilypad", key="enabled")
|
||||||
|
public boolean lilypadEnabled = true;
|
||||||
|
|
||||||
|
@CfgElement(category="reed", key="enabled")
|
||||||
|
public boolean reedEnabled = true;
|
||||||
|
|
||||||
|
@CfgElement(category="algae", key="enabled")
|
||||||
|
public boolean algaeEnabled = true;
|
||||||
|
|
||||||
|
@CfgElement(category="coral", key="enabled")
|
||||||
|
public boolean coralEnabled = true;
|
||||||
|
|
||||||
|
@CfgElement(category="leaves", key="horizontalOffset")
|
||||||
|
public OptionDouble leavesHOffset = new OptionDouble(0.0, 0.4, 0.025, 0.2);
|
||||||
|
|
||||||
|
@CfgElement(category="leaves", key="verticalOffset")
|
||||||
|
public OptionDouble leavesVOffset = new OptionDouble(0.0, 0.4, 0.025, 0.1);
|
||||||
|
|
||||||
|
@CfgElement(category="leaves", key="size")
|
||||||
|
public OptionDouble leavesSize = new OptionDouble(0.75, 1.8, 0.05, 1.4);
|
||||||
|
|
||||||
|
@CfgElement(category="grass", key="horizontalOffset")
|
||||||
|
public OptionDouble grassHOffset = new OptionDouble(0.0, 0.4, 0.025, 0.2);
|
||||||
|
|
||||||
|
@CfgElement(category="grass", key="heightMin")
|
||||||
|
@Limit(max="grassHeightMax")
|
||||||
|
public OptionDouble grassHeightMin = new OptionDouble(0.1, 1.5, 0.05, 0.5);
|
||||||
|
|
||||||
|
@CfgElement(category="grass", key="heightMax")
|
||||||
|
public OptionDouble grassHeightMax = new OptionDouble(0.1, 1.5, 0.05, 1.0);
|
||||||
|
|
||||||
|
@CfgElement(category="grass", key="size")
|
||||||
|
public OptionDouble grassSize = new OptionDouble(0.5, 1.5, 0.05, 1.0);
|
||||||
|
|
||||||
|
@CfgElement(category="lilypad", key="horizontalOffset")
|
||||||
|
public OptionDouble lilypadHOffset = new OptionDouble(0.0, 0.25, 0.025, 0.1);
|
||||||
|
|
||||||
|
@CfgElement(category="lilypad", key="chance")
|
||||||
|
public OptionInteger lilypadChance = new OptionInteger(0, 64, 1, 16);
|
||||||
|
|
||||||
|
@CfgElement(category="reed", key="horizontalOffset")
|
||||||
|
public OptionDouble reedHOffset = new OptionDouble(0.0, 0.25, 0.025, 0.1);
|
||||||
|
|
||||||
|
@CfgElement(category="reed", key="heightMin")
|
||||||
|
@Limit(max="reedHeightMax")
|
||||||
|
public OptionDouble reedHeightMin = new OptionDouble(1.5, 3.5, 0.1, 2.0);
|
||||||
|
|
||||||
|
@CfgElement(category="reed", key="heightMax")
|
||||||
|
public OptionDouble reedHeightMax = new OptionDouble(1.5, 3.5, 0.1, 2.5);
|
||||||
|
|
||||||
|
@CfgElement(category="reed", key="chance")
|
||||||
|
public OptionInteger reedChance = new OptionInteger(0, 64, 1, 32);
|
||||||
|
|
||||||
|
@CfgElement(category="algae", key="horizontalOffset")
|
||||||
|
public OptionDouble algaeHOffset = new OptionDouble(0.0, 0.25, 0.025, 0.1);
|
||||||
|
|
||||||
|
@CfgElement(category="algae", key="size")
|
||||||
|
public OptionDouble algaeSize = new OptionDouble(0.5, 1.5, 0.05, 1.0);
|
||||||
|
|
||||||
|
@CfgElement(category="algae", key="heightMin")
|
||||||
|
@Limit(max="algaeHeightMax")
|
||||||
|
public OptionDouble algaeHeightMin = new OptionDouble(0.1, 1.5, 0.05, 0.5);
|
||||||
|
|
||||||
|
@CfgElement(category="algae", key="heightMax")
|
||||||
|
public OptionDouble algaeHeightMax = new OptionDouble(0.1, 1.5, 0.05, 1.0);
|
||||||
|
|
||||||
|
@CfgElement(category="algae", key="chance")
|
||||||
|
public OptionInteger algaeChance = new OptionInteger(0, 64, 1, 48);
|
||||||
|
|
||||||
|
@CfgElement(category="coral", key="population")
|
||||||
|
public OptionInteger coralPopulation = new OptionInteger(0, 64, 1, 32);
|
||||||
|
|
||||||
|
@CfgElement(category="coral", key="chance")
|
||||||
|
public OptionInteger coralChance = new OptionInteger(0, 64, 1, 32);
|
||||||
|
|
||||||
|
@CfgElement(category="coral", key="verticalOffset")
|
||||||
|
public OptionDouble coralVOffset = new OptionDouble(0.0, 0.25, 0.025, 0.1);
|
||||||
|
|
||||||
|
@CfgElement(category="coral", key="horizontalOffset")
|
||||||
|
public OptionDouble coralHOffset = new OptionDouble(0.0, 0.4, 0.025, 0.2);
|
||||||
|
|
||||||
|
@CfgElement(category="coral", key="crustSize")
|
||||||
|
public OptionDouble coralCrustSize = new OptionDouble(0.75, 1.75, 0.05, 1.4);
|
||||||
|
|
||||||
|
@CfgElement(category="coral", key="size")
|
||||||
|
public OptionDouble coralSize = new OptionDouble(0.25, 1.0, 0.05, 0.7);
|
||||||
|
}
|
||||||
128
src/main/java/mods/betterfoliage/common/config/ConfigBase.java
Normal file
128
src/main/java/mods/betterfoliage/common/config/ConfigBase.java
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package mods.betterfoliage.common.config;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import net.minecraftforge.common.config.Configuration;
|
||||||
|
import net.minecraftforge.common.config.Property;
|
||||||
|
|
||||||
|
public class ConfigBase {
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public static @interface CfgElement {
|
||||||
|
String category();
|
||||||
|
String key();
|
||||||
|
String comment() default "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public static @interface Limit {
|
||||||
|
String min() default "";
|
||||||
|
String max() default "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Configuration config;
|
||||||
|
|
||||||
|
public void load(File configFile) {
|
||||||
|
config = new Configuration(configFile);
|
||||||
|
config.load();
|
||||||
|
|
||||||
|
for (Field field : getClass().getDeclaredFields()) {
|
||||||
|
CfgElement annot = field.getAnnotation(CfgElement.class);
|
||||||
|
if (annot == null) continue;
|
||||||
|
|
||||||
|
field.setAccessible(true);
|
||||||
|
if (field.getType().equals(boolean.class) || field.getType().equals(Boolean.class)) {
|
||||||
|
try {
|
||||||
|
Property prop = config.get(annot.category(), annot.key(), field.getBoolean(this));
|
||||||
|
field.setBoolean(this, prop.getBoolean(field.getBoolean(this)));
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
} else if (field.getType().equals(OptionInteger.class)) {
|
||||||
|
try {
|
||||||
|
OptionInteger option = (OptionInteger) field.get(this);
|
||||||
|
Property prop = config.get(annot.category(), annot.key(), option.value);
|
||||||
|
option.value = prop.getInt(option.value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
} else if (field.getType().equals(OptionDouble.class)) {
|
||||||
|
try {
|
||||||
|
OptionDouble option = (OptionDouble) field.get(this);
|
||||||
|
Property prop = config.get(annot.category(), annot.key(), option.value);
|
||||||
|
option.value = prop.getDouble(option.value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validateLimits();
|
||||||
|
if (config.hasChanged()) config.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateLimits() {
|
||||||
|
for (Field fieldThis : getClass().getDeclaredFields()) {
|
||||||
|
Limit annot = fieldThis.getAnnotation(Limit.class);
|
||||||
|
if (annot == null) continue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Field fieldMin = annot.min().isEmpty() ? null : getClass().getDeclaredField(annot.min());
|
||||||
|
Field fieldMax = annot.max().isEmpty() ? null : getClass().getDeclaredField(annot.max());
|
||||||
|
fieldThis.setAccessible(true);
|
||||||
|
fieldMin.setAccessible(true);
|
||||||
|
fieldMax.setAccessible(true);
|
||||||
|
|
||||||
|
if (fieldThis.getType().equals(OptionInteger.class)) {
|
||||||
|
OptionInteger optionThis = (OptionInteger) fieldThis.get(this);
|
||||||
|
OptionInteger optionMin = fieldMin == null ? null : (OptionInteger) fieldMin.get(this);
|
||||||
|
OptionInteger optionMax = fieldMax == null ? null : (OptionInteger) fieldMax.get(this);
|
||||||
|
if (optionMin != null) optionThis.value = Math.max(optionThis.value, optionMin.value);
|
||||||
|
if (optionMax != null) optionThis.value = Math.min(optionThis.value, optionMax.value);
|
||||||
|
} else if (fieldThis.getType().equals(OptionDouble.class)) {
|
||||||
|
OptionDouble optionThis = (OptionDouble) fieldThis.get(this);
|
||||||
|
OptionDouble optionMin = fieldMin == null ? null : (OptionDouble) fieldMin.get(this);
|
||||||
|
OptionDouble optionMax = fieldMax == null ? null : (OptionDouble) fieldMax.get(this);
|
||||||
|
if (optionMin != null) optionThis.value = Math.max(optionThis.value, optionMin.value);
|
||||||
|
if (optionMax != null) optionThis.value = Math.min(optionThis.value, optionMax.value);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
for (Field field : getClass().getDeclaredFields()) {
|
||||||
|
CfgElement annot = field.getAnnotation(CfgElement.class);
|
||||||
|
if (annot == null) continue;
|
||||||
|
|
||||||
|
field.setAccessible(true);
|
||||||
|
if (field.getType().equals(boolean.class) || field.getType().equals(Boolean.class)) {
|
||||||
|
try {
|
||||||
|
Property prop = config.get(annot.category(), annot.key(), field.getBoolean(this));
|
||||||
|
prop.set(field.getBoolean(this));
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
} else if (field.getType().equals(OptionInteger.class)) {
|
||||||
|
try {
|
||||||
|
OptionInteger option = (OptionInteger) field.get(this);
|
||||||
|
Property prop = config.get(annot.category(), annot.key(), option.value);
|
||||||
|
prop.set(option.value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
} else if (field.getType().equals(OptionDouble.class)) {
|
||||||
|
try {
|
||||||
|
OptionDouble option = (OptionDouble) field.get(this);
|
||||||
|
Property prop = config.get(annot.category(), annot.key(), option.value);
|
||||||
|
prop.set(option.value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package mods.betterfoliage.common.config;
|
||||||
|
|
||||||
|
public class OptionDouble {
|
||||||
|
|
||||||
|
public double min;
|
||||||
|
public double max;
|
||||||
|
public double step;
|
||||||
|
public double value;
|
||||||
|
|
||||||
|
public OptionDouble(double min, double max, double step, double value) {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.step = step;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void increment() {
|
||||||
|
value += step;
|
||||||
|
if (value > max) value = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decrement() {
|
||||||
|
value -= step;
|
||||||
|
if (value < min) value = min;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package mods.betterfoliage.common.config;
|
||||||
|
|
||||||
|
public class OptionInteger {
|
||||||
|
|
||||||
|
public int min;
|
||||||
|
public int max;
|
||||||
|
public int step;
|
||||||
|
public int value;
|
||||||
|
|
||||||
|
public OptionInteger(int min, int max, int step, int value) {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.step = step;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void increment() {
|
||||||
|
value += step;
|
||||||
|
if (value > max) value = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decrement() {
|
||||||
|
value -= step;
|
||||||
|
if (value < min) value = min;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/main/java/mods/betterfoliage/common/util/Double3.java
Normal file
42
src/main/java/mods/betterfoliage/common/util/Double3.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package mods.betterfoliage.common.util;
|
||||||
|
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
|
||||||
|
public class Double3 {
|
||||||
|
|
||||||
|
public final double x;
|
||||||
|
public final double y;
|
||||||
|
public final double z;
|
||||||
|
|
||||||
|
public Double3(double x, double y, double z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double3(ForgeDirection dir) {
|
||||||
|
this.x = dir.offsetX;
|
||||||
|
this.y = dir.offsetY;
|
||||||
|
this.z = dir.offsetZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double3 add(Double3 other) {
|
||||||
|
return new Double3(x + other.x, y + other.y, z + other.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double3 add(double x, double y, double z) {
|
||||||
|
return new Double3(this.x + x, this.y + y, this.z + z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double3 scaleAxes(double sx, double sy, double sz) {
|
||||||
|
return new Double3(x * sx, y * sy, z * sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double3 scale(double s) {
|
||||||
|
return new Double3(x * s, y * s, z * s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double3 inverse() {
|
||||||
|
return new Double3(-x, -y, -z);
|
||||||
|
}
|
||||||
|
}
|
||||||
94
src/main/java/mods/betterfoliage/common/util/Utils.java
Normal file
94
src/main/java/mods/betterfoliage/common/util/Utils.java
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
package mods.betterfoliage.common.util;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
|
||||||
|
import mods.betterfoliage.loader.DeobfHelper;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.resources.IResource;
|
||||||
|
import net.minecraft.client.resources.IResourceManager;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
|
||||||
|
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||||
|
|
||||||
|
public class Utils {
|
||||||
|
|
||||||
|
private Utils() {}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Map<String, IResourceManager> getDomainResourceManagers() {
|
||||||
|
IResourceManager manager = Minecraft.getMinecraft().getResourceManager();
|
||||||
|
Map<String, IResourceManager> result = getField(manager, "domainResourceManagers", Map.class);
|
||||||
|
if (result == null) result = getField(manager, DeobfHelper.transformElementSearge("domainResourceManagers"), Map.class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> T getField(Object target, String fieldName, Class<T> resultClass) {
|
||||||
|
try {
|
||||||
|
Field field = target.getClass().getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
return (T) field.get(target);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> T getStaticField(Class<?> clazz, String fieldName, Class<T> resultClass) {
|
||||||
|
try {
|
||||||
|
Field field = clazz.getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
return (T) field.get(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static ISimpleBlockRenderingHandler getRenderingHandler(int renderType) {
|
||||||
|
try {
|
||||||
|
Field field = RenderingRegistry.class.getDeclaredField("INSTANCE");
|
||||||
|
field.setAccessible(true);
|
||||||
|
RenderingRegistry inst = (RenderingRegistry) field.get(null);
|
||||||
|
field = RenderingRegistry.class.getDeclaredField("blockRenderers");
|
||||||
|
field.setAccessible(true);
|
||||||
|
return ((Map<Integer, ISimpleBlockRenderingHandler>) field.get(inst)).get(renderType);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean resourceExists(ResourceLocation resourceLocation) {
|
||||||
|
try {
|
||||||
|
IResource resource = Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation);
|
||||||
|
if (resource != null) return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copyFromTextResource(ResourceLocation resourceLocation, File target) {
|
||||||
|
try {
|
||||||
|
IResource defaults = Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation);
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(defaults.getInputStream(), Charsets.UTF_8));
|
||||||
|
FileWriter writer = new FileWriter(target);
|
||||||
|
|
||||||
|
String line = reader.readLine();
|
||||||
|
while(line != null) {
|
||||||
|
writer.write(line + System.lineSeparator());
|
||||||
|
line = reader.readLine();
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
writer.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package mods.betterfoliage.loader;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||||
|
|
||||||
|
@IFMLLoadingPlugin.TransformerExclusions({"mods.betterfoliage.loader"})
|
||||||
|
public class BetterFoliageLoader implements IFMLLoadingPlugin {
|
||||||
|
|
||||||
|
public String[] getASMTransformerClass() {
|
||||||
|
return new String[] {"mods.betterfoliage.loader.BetterFoliageTransformer"};
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModContainerClass() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSetupClass() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void injectData(Map<String, Object> data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccessTransformerClass() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package mods.betterfoliage.loader;
|
||||||
|
|
||||||
|
import net.minecraft.launchwrapper.IClassTransformer;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.FMLInjectionData;
|
||||||
|
|
||||||
|
public class BetterFoliageTransformer implements IClassTransformer {
|
||||||
|
|
||||||
|
protected Iterable<MethodTransformerBase> transformers = ImmutableList.<MethodTransformerBase>of(
|
||||||
|
new TransformRenderBlockOverride(),
|
||||||
|
new TransformShaderModBlockOverride()
|
||||||
|
);
|
||||||
|
|
||||||
|
protected Logger logger = LogManager.getLogger(getClass().getSimpleName());
|
||||||
|
|
||||||
|
public BetterFoliageTransformer() {
|
||||||
|
String mcVersion = FMLInjectionData.data()[4].toString();
|
||||||
|
if (!ImmutableList.<String>of("1.7.2", "1.7.10").contains(mcVersion))
|
||||||
|
logger.warn(String.format("Unsupported Minecraft version %s", mcVersion));
|
||||||
|
|
||||||
|
DeobfHelper.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||||
|
// ???
|
||||||
|
if (basicClass == null) return null;
|
||||||
|
|
||||||
|
// read class
|
||||||
|
ClassNode classNode = new ClassNode();
|
||||||
|
ClassReader classReader = new ClassReader(basicClass);
|
||||||
|
classReader.accept(classNode, 0);
|
||||||
|
boolean hasTransformed = false;
|
||||||
|
|
||||||
|
for (MethodTransformerBase transformer : transformers) {
|
||||||
|
// try to find specified method in class
|
||||||
|
if (!transformedName.equals(transformer.getClassName())) continue;
|
||||||
|
|
||||||
|
logger.debug(String.format("Found class: %s -> %s", name, transformedName));
|
||||||
|
for (MethodNode methodNode : classNode.methods) {
|
||||||
|
logger.trace(String.format("Checking method: %s, sig: %s", methodNode.name, methodNode.desc));
|
||||||
|
Boolean isObfuscated = null;
|
||||||
|
if (methodNode.name.equals(DeobfHelper.transformElementName(transformer.getMethodName())) && methodNode.desc.equals(DeobfHelper.transformSignature(transformer.getSignature()))) {
|
||||||
|
isObfuscated = true;
|
||||||
|
} else if (methodNode.name.equals(transformer.getMethodName()) && methodNode.desc.equals(transformer.getSignature())) {
|
||||||
|
isObfuscated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isObfuscated != null) {
|
||||||
|
// transform
|
||||||
|
hasTransformed = true;
|
||||||
|
try {
|
||||||
|
transformer.transform(methodNode, isObfuscated);
|
||||||
|
logger.info(String.format("%s: SUCCESS", transformer.getLogMessage()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.info(String.format("%s: FAILURE", transformer.getLogMessage()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return result
|
||||||
|
ClassWriter writer = new ClassWriter(0);
|
||||||
|
if (hasTransformed) classNode.accept(writer);
|
||||||
|
return !hasTransformed ? basicClass : writer.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
62
src/main/java/mods/betterfoliage/loader/DeobfHelper.java
Normal file
62
src/main/java/mods/betterfoliage/loader/DeobfHelper.java
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package mods.betterfoliage.loader;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.FMLInjectionData;
|
||||||
|
|
||||||
|
public class DeobfHelper {
|
||||||
|
|
||||||
|
private static Map<String, String> obfClasses = Maps.newHashMap();
|
||||||
|
private static Map<String, String> obfElements = Maps.newHashMap();
|
||||||
|
private static Map<String, String> srgElements = Maps.newHashMap();
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
String mcVersion = FMLInjectionData.data()[4].toString();
|
||||||
|
srgElements.put("domainResourceManagers", "field_110548_a");
|
||||||
|
srgElements.put("mapRegisteredSprites", "field_110574_e");
|
||||||
|
if ("1.7.2".equals(mcVersion)) {
|
||||||
|
obfClasses.put("net/minecraft/client/renderer/RenderBlocks", "ble");
|
||||||
|
obfClasses.put("net/minecraft/world/IBlockAccess", "afx");
|
||||||
|
obfClasses.put("net/minecraft/block/Block", "ahu");
|
||||||
|
|
||||||
|
obfElements.put("blockAccess", "a");
|
||||||
|
obfElements.put("renderBlockByRenderType", "b");
|
||||||
|
obfElements.put("mapRegisteredSprites", "bpr");
|
||||||
|
} else if ("1.7.10".equals(mcVersion)) {
|
||||||
|
obfClasses.put("net/minecraft/client/renderer/RenderBlocks", "blm");
|
||||||
|
obfClasses.put("net/minecraft/world/IBlockAccess", "ahl");
|
||||||
|
obfClasses.put("net/minecraft/block/Block", "aji");
|
||||||
|
|
||||||
|
obfElements.put("blockAccess", "a");
|
||||||
|
obfElements.put("renderBlockByRenderType", "b");
|
||||||
|
obfElements.put("mapRegisteredSprites", "bpr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String transformClassName(String className) {
|
||||||
|
return obfClasses.containsKey(className) ? obfClasses.get(className) : className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String transformElementName(String elementName) {
|
||||||
|
return obfElements.containsKey(elementName) ? obfElements.get(elementName) : elementName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String transformElementSearge(String elementName) {
|
||||||
|
return srgElements.containsKey(elementName) ? srgElements.get(elementName) : elementName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String transformSignature(String signature) {
|
||||||
|
String result = signature;
|
||||||
|
boolean hasChanged = false;
|
||||||
|
do {
|
||||||
|
hasChanged = false;
|
||||||
|
for (Map.Entry<String, String> entry : obfClasses.entrySet()) if (result.contains("L" + entry.getKey() + ";")) {
|
||||||
|
result = result.replace("L" + entry.getKey() + ";", "L" + entry.getValue() + ";");
|
||||||
|
hasChanged = true;
|
||||||
|
}
|
||||||
|
} while(hasChanged);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package mods.betterfoliage.loader;
|
||||||
|
|
||||||
|
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
|
import org.objectweb.asm.tree.InsnList;
|
||||||
|
import org.objectweb.asm.tree.MethodInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
|
||||||
|
public abstract class MethodTransformerBase {
|
||||||
|
|
||||||
|
public static interface IInstructionMatch {
|
||||||
|
public boolean matches(AbstractInsnNode node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getClassName();
|
||||||
|
public abstract String getMethodName();
|
||||||
|
public abstract String getSignature();
|
||||||
|
public abstract String getLogMessage();
|
||||||
|
|
||||||
|
public abstract void transform(MethodNode method, boolean obf);
|
||||||
|
|
||||||
|
protected static String className(String className, boolean isObfuscated) {
|
||||||
|
return isObfuscated ? DeobfHelper.transformClassName(className) : className;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String element(String fieldName, boolean isObfuscated) {
|
||||||
|
return isObfuscated ? DeobfHelper.transformElementName(fieldName) : fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String signature(String signature, boolean isObfuscated) {
|
||||||
|
return isObfuscated ? DeobfHelper.transformSignature(signature) : signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractInsnNode findNext(AbstractInsnNode start, IInstructionMatch match) {
|
||||||
|
AbstractInsnNode current = start;
|
||||||
|
while(current != null) {
|
||||||
|
if (match.matches(current)) break;
|
||||||
|
current = current.getNext();
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractInsnNode findPrevious(AbstractInsnNode start, IInstructionMatch match) {
|
||||||
|
AbstractInsnNode current = start;
|
||||||
|
while(current != null) {
|
||||||
|
if (match.matches(current)) break;
|
||||||
|
current = current.getPrevious();
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IInstructionMatch matchInvokeAny() {
|
||||||
|
return new IInstructionMatch() {
|
||||||
|
public boolean matches(AbstractInsnNode node) {
|
||||||
|
return node instanceof MethodInsnNode;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IInstructionMatch matchOpcode(final int opcode) {
|
||||||
|
return new IInstructionMatch() {
|
||||||
|
public boolean matches(AbstractInsnNode node) {
|
||||||
|
return node.getOpcode() == opcode;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void insertAfter(InsnList insnList, AbstractInsnNode node, AbstractInsnNode... added) {
|
||||||
|
InsnList listAdd = new InsnList();
|
||||||
|
for (AbstractInsnNode inst : added) listAdd.add(inst);
|
||||||
|
insnList.insert(node, listAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package mods.betterfoliage.loader;
|
||||||
|
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
|
import org.objectweb.asm.tree.FieldInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
import org.objectweb.asm.tree.VarInsnNode;
|
||||||
|
|
||||||
|
public class TransformRenderBlockOverride extends MethodTransformerBase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClassName() {
|
||||||
|
return "net.minecraft.client.renderer.RenderBlocks";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMethodName() {
|
||||||
|
return "renderBlockByRenderType";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSignature() {
|
||||||
|
return "(Lnet/minecraft/block/Block;III)Z";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLogMessage() {
|
||||||
|
return "Applying RenderBlocks.renderBlockByRenderType() render type ovverride";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transform(MethodNode method, boolean obf) {
|
||||||
|
AbstractInsnNode invokeGetRenderType = findNext(method.instructions.getFirst(), matchInvokeAny());
|
||||||
|
AbstractInsnNode storeRenderType = findNext(invokeGetRenderType, matchOpcode(Opcodes.ISTORE));
|
||||||
|
insertAfter(method.instructions, storeRenderType,
|
||||||
|
new VarInsnNode(Opcodes.ALOAD, 0),
|
||||||
|
new FieldInsnNode(Opcodes.GETFIELD, className("net/minecraft/client/renderer/RenderBlocks", obf), element("blockAccess", obf), signature("Lnet/minecraft/world/IBlockAccess;", obf)),
|
||||||
|
new VarInsnNode(Opcodes.ILOAD, 2),
|
||||||
|
new VarInsnNode(Opcodes.ILOAD, 3),
|
||||||
|
new VarInsnNode(Opcodes.ILOAD, 4),
|
||||||
|
new VarInsnNode(Opcodes.ALOAD, 1),
|
||||||
|
new VarInsnNode(Opcodes.ILOAD, 5),
|
||||||
|
new MethodInsnNode(Opcodes.INVOKESTATIC, "mods/betterfoliage/client/BetterFoliageClient", "getRenderTypeOverride", signature("(Lnet/minecraft/world/IBlockAccess;IIILnet/minecraft/block/Block;I)I", obf)),
|
||||||
|
new VarInsnNode(Opcodes.ISTORE, 5)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package mods.betterfoliage.loader;
|
||||||
|
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
import org.objectweb.asm.tree.VarInsnNode;
|
||||||
|
|
||||||
|
public class TransformShaderModBlockOverride extends MethodTransformerBase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClassName() {
|
||||||
|
return "shadersmodcore.client.Shaders";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMethodName() {
|
||||||
|
return "pushEntity";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSignature() {
|
||||||
|
return "(Lnet/minecraft/client/renderer/RenderBlocks;Lnet/minecraft/block/Block;III)V";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLogMessage() {
|
||||||
|
return "Applying Shaders.pushEntity() block id ovverride";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transform(MethodNode method, boolean obf) {
|
||||||
|
AbstractInsnNode arrayStore = findNext(method.instructions.getFirst(), matchOpcode(Opcodes.IASTORE));
|
||||||
|
insertAfter(method.instructions, arrayStore.getPrevious(),
|
||||||
|
new VarInsnNode(Opcodes.ALOAD, 1),
|
||||||
|
new MethodInsnNode(Opcodes.INVOKESTATIC, "mods/betterfoliage/client/ShadersModIntegration", "getBlockIdOverride", signature("(ILnet/minecraft/block/Block;)I", obf))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// Vanilla
|
||||||
|
net.minecraft.block.BlockTallGrass
|
||||||
|
net.minecraft.block.BlockCrops
|
||||||
|
net.minecraft.block.BlockReed
|
||||||
|
net.minecraft.block.BlockDoublePlant
|
||||||
|
-net.minecraft.block.BlockCarrot
|
||||||
|
-net.minecraft.block.BlockPotato
|
||||||
|
|
||||||
|
// Biomes O'Plenty
|
||||||
|
biomesoplenty.common.blocks.BlockBOPFlower
|
||||||
|
biomesoplenty.common.blocks.BlockBOPFlower2
|
||||||
|
|
||||||
|
// Tinkers' Construct
|
||||||
|
tconstruct.blocks.slime.SlimeTallGrass
|
||||||
|
|
||||||
|
// Plant Mega Pack
|
||||||
|
plantmegapack.block.PMPBlockBerrybush
|
||||||
|
plantmegapack.block.PMPBlockCrops
|
||||||
|
plantmegapack.block.PMPBlockDesert
|
||||||
|
plantmegapack.block.PMPBlockFern
|
||||||
|
plantmegapack.block.PMPBlockFlowerMulti
|
||||||
|
plantmegapack.block.PMPBlockFlowerSingle
|
||||||
|
plantmegapack.block.PMPBlockForest
|
||||||
|
plantmegapack.block.PMPBlockGrass
|
||||||
|
plantmegapack.block.PMPBlockJungle
|
||||||
|
plantmegapack.block.PMPBlockMountain
|
||||||
|
plantmegapack.block.PMPBlockSavanna
|
||||||
|
plantmegapack.block.PMPBlockShrub
|
||||||
|
plantmegapack.block.PMPBlockWetlands
|
||||||
|
|
||||||
|
// Pam's HarvestCraft
|
||||||
|
com.pam.harvestcraft.BlockPamCrop
|
||||||
|
com.pam.harvestcraft.BlockPamDesertGarden
|
||||||
|
com.pam.harvestcraft.BlockPamNormalGarden
|
||||||
|
com.pam.harvestcraft.BlockPamWaterGarden
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
net.minecraft.block.BlockLeavesBase
|
||||||
|
forestry.arboriculture.gadgets.BlockLeaves
|
||||||
|
thaumcraft.common.blocks.BlockMagicalLeaves
|
||||||
|
-tconstruct.blocks.OreberryBushEssence
|
||||||
31
src/main/resources/assets/betterfoliage/lang/en_US.lang
Normal file
31
src/main/resources/assets/betterfoliage/lang/en_US.lang
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
key.betterfoliage.gui=Open Settings
|
||||||
|
|
||||||
|
message.betterfoliage.optionOn=ON
|
||||||
|
message.betterfoliage.optionOff=OFF
|
||||||
|
message.betterfoliage.config=Config
|
||||||
|
message.betterfoliage.back=Back
|
||||||
|
message.betterfoliage.close=Close
|
||||||
|
|
||||||
|
message.betterfoliage.betterLeaves=Extra Leaves: %s
|
||||||
|
message.betterfoliage.betterGrass=Short Grass: %s
|
||||||
|
message.betterfoliage.betterCactus=Better Cactus: %s
|
||||||
|
message.betterfoliage.betterLilypad=Better Lilypad: %s
|
||||||
|
message.betterfoliage.betterReed=Reeds: %s
|
||||||
|
message.betterfoliage.betterAlgae=Algae: %s
|
||||||
|
message.betterfoliage.betterCoral=Coral: %s
|
||||||
|
|
||||||
|
message.betterfoliage.size=Size
|
||||||
|
message.betterfoliage.hOffset=H.Offset
|
||||||
|
message.betterfoliage.vOffset=V.Offset
|
||||||
|
message.betterfoliage.minHeight=Min.Height
|
||||||
|
message.betterfoliage.maxHeight=Max.Height
|
||||||
|
message.betterfoliage.flowerChance=Flower Chance
|
||||||
|
message.betterfoliage.reedChance=Reed Population
|
||||||
|
message.betterfoliage.leavesMode=Leaves Offset: %s
|
||||||
|
message.betterfoliage.genShortgrass=Use generated: %s
|
||||||
|
message.betterfoliage.leavesSkew=Skew
|
||||||
|
message.betterfoliage.leavesTranslate=Translate
|
||||||
|
message.betterfoliage.algaeChance=Algae Population
|
||||||
|
message.betterfoliage.crustSize=Crust Size
|
||||||
|
message.betterfoliage.coralChance=Coral Chance
|
||||||
|
message.betterfoliage.coralPopulation=Coral Population
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 305 B |
Binary file not shown.
|
After Width: | Height: | Size: 176 B |
Binary file not shown.
|
After Width: | Height: | Size: 345 B |
Binary file not shown.
|
After Width: | Height: | Size: 219 B |
Binary file not shown.
|
After Width: | Height: | Size: 102 B |
8
src/main/resources/mcmod.info
Normal file
8
src/main/resources/mcmod.info
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[{
|
||||||
|
"modid": "BetterFoliage",
|
||||||
|
"name": "Better Foliage",
|
||||||
|
"version": "$version",
|
||||||
|
"mcversion": "$mcversion",
|
||||||
|
"description": "Leafier leaves and grassier grass",
|
||||||
|
"authorList" : ["octarine-noise"]
|
||||||
|
}]
|
||||||
Reference in New Issue
Block a user