Skip to content

Commit

Permalink
Make it work
Browse files Browse the repository at this point in the history
  • Loading branch information
SoniEx2 committed Oct 22, 2015
1 parent 0da446c commit 430f849
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 27 deletions.
9 changes: 8 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ plugins {
id "net.minecraftforge.gradle.forge" version "2.0.1"
}

version = "1.0.0"
version = "0.1.0"
group= "com.github.soniex2.notebetter" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "notebetter"

Expand All @@ -37,6 +37,13 @@ minecraft {
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
}

jar {
manifest {
attributes 'FMLCorePlugin': 'com.github.soniex2.notebetter.NoteBetterCore'
attributes 'FMLCorePluginContainsFMLMod': 'true'
}
}

dependencies {
// you may put jars on which you depend on in ./libs
// or you may define them like so..
Expand Down
41 changes: 28 additions & 13 deletions src/main/java/com/github/soniex2/notebetter/NoteBetter.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,55 @@
package com.github.soniex2.notebetter;

import com.github.soniex2.notebetter.config.NoteBetterNoteConfig;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

import java.io.File;
import java.io.IOException;
import java.io.*;

@Mod(modid = NoteBetter.MODID, name = "NoteBetter", version = NoteBetter.VERSION,
acceptedMinecraftVersions = "1.8", acceptableRemoteVersions = "*",
guiFactory = "com.github.soniex2.notebetter.NoteBetterGuiFactory")
public class NoteBetter {
public static final String MODID = "notebetter";
public static final String VERSION = "1.0.0";
public static final String VERSION = "0.1.0";

@Mod.Instance
public static NoteBetter instance;

public File nbConfigDir;
public NoteBetterNoteConfig defaultConfig;

private void loadGlobalConfigs(File configDir) {
private void loadGlobalConfigs(File configDir) {
nbConfigDir = new File(configDir, "notebetter");
if (nbConfigDir.exists() || nbConfigDir.mkdir()) {
File defaultConfig = new File(nbConfigDir, "default.json");
try {
if (defaultConfig.exists() || defaultConfig.createNewFile()) {

boolean writeConf = false;
InputStream is;
if (defaultConfig.exists()) {
is = new FileInputStream(defaultConfig);
} else {
writeConf = true;
is = getClass().getResourceAsStream("/assets/notebetter/default.json");
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes = new byte[4096];
int l;
while ((l = is.read(bytes)) != -1) {
baos.write(bytes, 0, l);
}
is.close();
if (writeConf) {
OutputStream os = new FileOutputStream(defaultConfig);
baos.writeTo(os);
os.close();
}
String contents = baos.toString("UTF-8");
baos.close();
this.defaultConfig = NoteBetterNoteConfig.fromString(contents);
} catch (IOException e) {
throw new RuntimeException(e);
throw new RuntimeException("Couldn't create NoteBetter config!", e);
}
} else {
throw new RuntimeException("Couldn't create NoteBetter config dir!");
Expand All @@ -40,9 +60,4 @@ private void loadGlobalConfigs(File configDir) {
public void preInit(FMLPreInitializationEvent event) {
loadGlobalConfigs(event.getModConfigurationDirectory());
}

@EventHandler
public void init(FMLInitializationEvent event) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.github.soniex2.notebetter;

import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;

import java.util.HashMap;
import java.util.ListIterator;
import java.util.Map;

/**
* @author soniex2
*/
public class NoteBetterClassTransformer implements IClassTransformer {
private Map<String, String> maps;
private boolean isObfuscated;

private void setupDeobfMaps() {
maps = new HashMap<String, String>();
maps.put("te_mname", "triggerNote");
maps.put("te_mdesc", "(Lnet/minecraft/world/World;Lnet/minecraft/util/BlockPos;)V");
maps.put("nm_te_hndlr_desc", "(Lnet/minecraft/world/World;Lnet/minecraft/util/BlockPos;)Z");
}

private void setupObfMaps() {
maps = new HashMap<String, String>();
maps.put("te_mname", "func_175108_a");
maps.put("te_mdesc", "(Lnet/minecraft/world/World;Lnet/minecraft/util/BlockPos;)V");
maps.put("nm_te_hndlr_desc", "(Lnet/minecraft/world/World;Lnet/minecraft/util/BlockPos;)Z");
}

@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
isObfuscated = !name.equals(transformedName);
if (transformedName.equals("net.minecraft.tileentity.TileEntityNote"))
return transformTileEntityNote(basicClass);
return basicClass;
}

private byte[] transformTileEntityNote(byte[] basicClass) {
if (isObfuscated) setupObfMaps();
else setupDeobfMaps();

System.out.println("Transforming TileEntityNote");

try {
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(basicClass);
classReader.accept(classNode, 0);

boolean transformed = false;

for (MethodNode m : classNode.methods) {
if (m.name.equals(maps.get("te_mname")) && m.desc.equals(maps.get("te_mdesc"))) {
ListIterator<AbstractInsnNode> it = m.instructions.iterator();
System.out.println("Transforming TileEntityNote.triggerNote");
VarInsnNode vigetWorld = new VarInsnNode(Opcodes.ALOAD, 1);
it.add(vigetWorld);
VarInsnNode vigetPos = new VarInsnNode(Opcodes.ALOAD, 2);
it.add(vigetPos);
MethodInsnNode call = new MethodInsnNode(Opcodes.INVOKESTATIC,
"com/github/soniex2/notebetter/NoteMethods",
"handleTileEntity",
maps.get("nm_te_hndlr_desc"),
false);
it.add(call);
LabelNode cont = new LabelNode();
JumpInsnNode test = new JumpInsnNode(Opcodes.IFEQ, cont);
it.add(test);
InsnNode ret = new InsnNode(Opcodes.RETURN);
it.add(ret);
it.add(cont);
System.out.println("Done!");
transformed = true;
}
}
if (!transformed)
System.out.println("Failed to transform TileEntityNote.triggerNote");

ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);

if (transformed)
System.out.println("Transforming TileEntityNote - Success!");
else
System.out.println("Transforming TileEntityNote - Failed!");
return writer.toByteArray();
} catch (Exception e) {
System.out.println("Transforming TileEntityNote - Failed!");
e.printStackTrace();
}

return basicClass;
}
}
62 changes: 62 additions & 0 deletions src/main/java/com/github/soniex2/notebetter/NoteBetterCore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.github.soniex2.notebetter;

import net.minecraftforge.fml.common.DummyModContainer;
import net.minecraftforge.fml.common.ModMetadata;
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;

import java.util.Map;

/**
* @author soniex2
*/
@IFMLLoadingPlugin.MCVersion("1.8")
@IFMLLoadingPlugin.TransformerExclusions("com.github.soniex2.notebetter")
@IFMLLoadingPlugin.SortingIndex(Integer.MAX_VALUE)
public class NoteBetterCore implements IFMLLoadingPlugin {
public static class NoteBetterCoreModContainer extends DummyModContainer {
public NoteBetterCoreModContainer(){
super(new ModMetadata());
}
}
/**
* @inheritDoc
*/
@Override
public String[] getASMTransformerClass() {
return new String[] {
"com.github.soniex2.notebetter.NoteBetterClassTransformer"
};
}

/**
* @inheritDoc
*/
@Override
public String getModContainerClass() {
return null;//"com.github.soniex2.notebetter.NoteBetterCore$NoteBetterCoreModContainer";
}

/**
* @inheritDoc
*/
@Override
public String getSetupClass() {
return null;
}

/**
* @inheritDoc
*/
@Override
public void injectData(Map<String, Object> data) {

}

/**
* @inheritDoc
*/
@Override
public String getAccessTransformerClass() {
return null;
}
}
106 changes: 106 additions & 0 deletions src/main/java/com/github/soniex2/notebetter/NoteMethods.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.github.soniex2.notebetter;

import com.github.soniex2.notebetter.config.NoteBetterNoteConfig;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntityNote;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.NoteBlockEvent;

/**
* @author soniex2
*/
public class NoteMethods {
private static NoteBlockEvent.Instrument instrumentFromString(String instrument) {
if (instrument.startsWith("minecraft:note.")) {
String name = instrument.substring(15); // skip above prefix
switch (name.charAt(0)) {
case 'h':
if (name.equals("harp"))
return NoteBlockEvent.Instrument.PIANO;
else if (name.equals("hat"))
return NoteBlockEvent.Instrument.CLICKS;
break;
case 'b':
if (name.equals("bd"))
return NoteBlockEvent.Instrument.BASSDRUM;
else if (name.equals("bassattack"))
return NoteBlockEvent.Instrument.BASSGUITAR;
break;
case 's':
if (name.equals("snare"))
return NoteBlockEvent.Instrument.SNARE;
break;
}
}
return null;
}

private static String instrumentToString(NoteBlockEvent.Instrument instrument) {
switch (instrument) {
default:
return "minecraft:note.harp";
case BASSDRUM:
return "minecraft:note.bd";
case SNARE:
return "minecraft:note.snare";
case CLICKS:
return "minecraft:note.hat";
case BASSGUITAR:
return "minecraft:note.bassattack";
}
}

private static void playNote(World world, BlockPos pos, String instrument, int note) {
NoteBlockEvent.Instrument vanillaInstrument = instrumentFromString(instrument);
if (vanillaInstrument != null) {
NoteBlockEvent.Play e = new NoteBlockEvent.Play(world, pos, world.getBlockState(pos), note, vanillaInstrument.ordinal());
if (MinecraftForge.EVENT_BUS.post(e)) return;
vanillaInstrument = e.instrument;
instrument = instrumentToString(vanillaInstrument);
note = e.getVanillaNoteId();
}
float pitch = (float) Math.pow(2.0D, (note - 12) / 12.0D);
world.playSoundEffect(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, instrument, 3.0F, pitch);
if (world instanceof WorldServer) // just in case it *isn't* being called from a WorldServer
((WorldServer) world).spawnParticle(EnumParticleTypes.NOTE, false, pos.getX() + 0.5D, pos.getY() + 1.2D, pos.getZ() + 0.5D, 0, ((double) note) / 24.0D, 0.0D, 0.0D, 1.0D);
}

public static boolean handleTileEntity(World world, BlockPos pos) {
if (world.getBlockState(pos.up()).getBlock().getMaterial() == Material.air) {
if (!(world.getTileEntity(pos) instanceof TileEntityNote)) return false;
TileEntityNote te = ((TileEntityNote) world.getTileEntity(pos));
/* First we do blocks */
IBlockState bs = world.getBlockState(pos.down());
ResourceLocation rl = (ResourceLocation) Block.blockRegistry.getNameForObject(bs.getBlock());
if (NoteBetter.instance.defaultConfig.blocks.containsKey(rl.toString())) {
String sound = NoteBetter.instance.defaultConfig.blocks.get(rl.toString());
if (sound == null) return true; // don't play anything
playNote(world, pos, sound, te.note);
return true;
}
/* Then we do materials */
Material m = world.getBlockState(pos.down()).getBlock().getMaterial();
for (NoteBetterNoteConfig.MaterialSound ms : NoteBetter.instance.defaultConfig.materials) {
if (ms.material_of == null) continue;
if (Block.getBlockFromName(ms.material_of).getMaterial() == m) {
if (ms.sound == null) return true; // don't play anything
playNote(world, pos, ms.sound, te.note);
return true;
}
}
/* Fallback to default */
if (NoteBetter.instance.defaultConfig.base != null) {
playNote(world, pos, NoteBetter.instance.defaultConfig.base, te.note);
return true;
}
}
return false;
}
}
Loading

0 comments on commit 430f849

Please sign in to comment.