269 lines
9.4 KiB
Java
269 lines
9.4 KiB
Java
package net.minecraft.src.forge;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.lang.reflect.Field;
|
|
|
|
import paulscode.sound.SoundSystemConfig;
|
|
import paulscode.sound.codecs.CodecIBXM;
|
|
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.src.*;
|
|
|
|
public class ModCompatibilityClient
|
|
{
|
|
/**
|
|
* Trys to get the class for the specified name, will also try the
|
|
* net.minecraft.src package in case we are in MCP
|
|
* Returns null if not found.
|
|
*
|
|
* @param name The class name
|
|
* @return The Class, or null if not found
|
|
*/
|
|
private static Class getClass(String name)
|
|
{
|
|
try
|
|
{
|
|
return Class.forName(name);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
try
|
|
{
|
|
return Class.forName("net.minecraft.src." + name);
|
|
}
|
|
catch (Exception e2)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************************************
|
|
* Risugami's AudioMod Compatibility
|
|
* http://www.minecraftforum.net/topic/75440-
|
|
*
|
|
* AudioMod adds a few extra codecs, loads audio from /resources/mods/*,
|
|
* introduces the concept of 'cave' sounds, which are determined by if
|
|
* the player is underneath a solid block.
|
|
*
|
|
* It also lowers the interval between background music songs to 6000
|
|
*/
|
|
public static SoundPool audioModSoundPoolCave;
|
|
|
|
/**
|
|
* Populates the sound pools with with sounds from the /resources/mods folder
|
|
* And sets the interval between background music to 6000
|
|
*
|
|
* @param mngr The SoundManager instance
|
|
*/
|
|
public static void audioModLoad(SoundManager mngr)
|
|
{
|
|
audioModSoundPoolCave = new SoundPool();
|
|
audioModLoadModAudio("resources/mod/sound", mngr.getSoundsPool());
|
|
audioModLoadModAudio("resources/mod/streaming", mngr.getStreamingPool());
|
|
audioModLoadModAudio("resources/mod/music", mngr.getMusicPool());
|
|
audioModLoadModAudio("resources/mod/cavemusic", audioModSoundPoolCave);
|
|
|
|
if (mngr.MUSIC_INTERVAL == 12000)
|
|
{
|
|
mngr.MUSIC_INTERVAL = 6000;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Walks the given path in the Minecraft app directory and adds audio to the SoundPool
|
|
* @param path The path to walk
|
|
* @param pool The pool to add sound to
|
|
*/
|
|
private static void audioModLoadModAudio(String path, SoundPool pool)
|
|
{
|
|
File folder = new File(Minecraft.getMinecraftDir(), path);
|
|
|
|
try
|
|
{
|
|
audioModWalkFolder(folder, folder, pool);
|
|
}
|
|
catch (IOException ex)
|
|
{
|
|
ModLoader.getLogger().fine("Loading Mod audio failed for folder: " + path);
|
|
ModLoader.getLogger().fine(ex.toString());
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Walks the folder path recursively and calls pool.addSound on any file it finds.
|
|
*
|
|
* @param base The base path for the folder, determines the name when calling addSound
|
|
* @param folder The current folder
|
|
* @param pool The SoundPool to add the sound to
|
|
* @throws IOException
|
|
*/
|
|
private static void audioModWalkFolder(File base, File folder, SoundPool pool) throws IOException
|
|
{
|
|
if (folder.exists() || folder.mkdirs())
|
|
{
|
|
for (File file : folder.listFiles())
|
|
{
|
|
if (!file.getName().startsWith("."))
|
|
{
|
|
if (file.isDirectory())
|
|
{
|
|
audioModWalkFolder(base, file, pool);
|
|
}
|
|
else if (file.isFile())
|
|
{
|
|
String subpath = file.getPath().substring(base.getPath().length() + 1).replace('\\', '/');
|
|
pool.addSound(subpath, file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds the IBXM codec and associates it with .xm, .s3m, and .mod
|
|
*/
|
|
public static void audioModAddCodecs()
|
|
{
|
|
SoundSystemConfig.setCodec("xm", CodecIBXM.class);
|
|
SoundSystemConfig.setCodec("s3m", CodecIBXM.class);
|
|
SoundSystemConfig.setCodec("mod", CodecIBXM.class);
|
|
}
|
|
|
|
/**
|
|
* If the current player is underground, it picks a random song from the cave sound pool,
|
|
* if they are not it returns the passed in entry.
|
|
*
|
|
* @param soundManager The SoundManager instance
|
|
* @param current The currently selected entry
|
|
* @return A soundPool entry to be played as the background music
|
|
*/
|
|
public static SoundPoolEntry audioModPickBackgroundMusic(SoundManager soundManager, SoundPoolEntry current)
|
|
{
|
|
Minecraft mc = ModLoader.getMinecraftInstance();
|
|
if (mc != null && mc.theWorld != null && audioModSoundPoolCave != null)
|
|
{
|
|
Entity ent = mc.renderViewEntity;
|
|
int x = MathHelper.func_40346_b(ent.posX);
|
|
int y = MathHelper.func_40346_b(ent.posY);
|
|
int z = MathHelper.func_40346_b(ent.posZ);
|
|
return (mc.theWorld.canBlockSeeTheSky(x, y, z) ? current : audioModSoundPoolCave.getRandomSound());
|
|
}
|
|
return current;
|
|
}
|
|
|
|
/***********************************************************************************************************
|
|
* SDK's ModLoaderMP
|
|
* http://www.minecraftforum.net/topic/86765-
|
|
*
|
|
* ModLoaderMP was supposed to be a reliable server side version of ModLoader, however it has
|
|
* gotten the reputation of being really slow to update. Never having bugfixes, breaking compatibility
|
|
* with the client side ModLoader.
|
|
*
|
|
* So we have replaced it with our own system called FML (Forge ModLoader)
|
|
* it is a stand alone mod, that Forge relies on, and that is open source/community driven.
|
|
* https://github.com/cpw/FML
|
|
*
|
|
* However, for compatibilities sake, we provide the ModLoaderMP's hooks so that the end user
|
|
* does not need to make a choice between the two on the client side.
|
|
**/
|
|
private static int isMLMPInstalled = -1;
|
|
|
|
/**
|
|
* Determine if ModLoaderMP is installed by checking for the existence of the BaseModMp class.
|
|
* @return True if BaseModMp was installed (indicating the existance of MLMP)
|
|
*/
|
|
public static boolean isMLMPInstalled()
|
|
{
|
|
if (isMLMPInstalled == -1)
|
|
{
|
|
isMLMPInstalled = (getClass("ModLoaderMp") != null ? 1 : 0);
|
|
}
|
|
return isMLMPInstalled == 1;
|
|
}
|
|
|
|
/**
|
|
* Attempts to spawn a vehicle using ModLoaderMP's vehicle spawn registry, if MLMP is not installed
|
|
* it returns the passed in currentEntity
|
|
*
|
|
* @param type The Type ID of the vehicle
|
|
* @param world The current world
|
|
* @param x The spawn X position
|
|
* @param y The spawn Y position
|
|
* @param z The spawn Z position
|
|
* @param thrower The entity that spawned the vehicle {possibly null}
|
|
* @param currentEntity The current value to return if MLMP is not installed
|
|
* @return The new spawned entity
|
|
* @throws Exception
|
|
*/
|
|
public static Object mlmpVehicleSpawn(int type, World world, double x, double y, double z, Entity thrower, Object currentEntity) throws Exception
|
|
{
|
|
Class mlmp = getClass("ModLoaderMp");
|
|
if (!isMLMPInstalled() || mlmp == null)
|
|
{
|
|
return currentEntity;
|
|
}
|
|
|
|
Object entry = mlmp.getDeclaredMethod("handleNetClientHandlerEntities", int.class).invoke(null, type);
|
|
if (entry == null)
|
|
{
|
|
return currentEntity;
|
|
}
|
|
|
|
Class entityClass = (Class)entry.getClass().getDeclaredField("entityClass").get(entry);
|
|
Object ret = (Entity)entityClass.getConstructor(World.class, Double.TYPE, Double.TYPE, Double.TYPE).newInstance(world, x, y, z);
|
|
|
|
if (entry.getClass().getDeclaredField("entityHasOwner").getBoolean(entry))
|
|
{
|
|
Field owner = entityClass.getField("owner");
|
|
|
|
if (!Entity.class.isAssignableFrom(owner.getType()))
|
|
{
|
|
throw new Exception(String.format("Entity\'s owner field must be of type Entity, but it is of type %s.", owner.getType()));
|
|
}
|
|
|
|
if (thrower == null)
|
|
{
|
|
System.out.println("Received spawn packet for entity with owner, but owner was not found.");
|
|
ModLoader.getLogger().fine("Received spawn packet for entity with owner, but owner was not found.");
|
|
}
|
|
else
|
|
{
|
|
if (!owner.getType().isAssignableFrom(thrower.getClass()))
|
|
{
|
|
throw new Exception(String.format("Tried to assign an entity of type %s to entity owner, which is of type %s.", thrower.getClass(), owner.getType()));
|
|
}
|
|
|
|
owner.set(ret, thrower);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Attempts to invoke ModLoaderMp.handleGUI if ModLoaderMP is installed.
|
|
* If not, it does nothing
|
|
*
|
|
* @param pkt The open window packet
|
|
*/
|
|
public static void mlmpOpenWindow(Packet100OpenWindow pkt)
|
|
{
|
|
Class mlmp = getClass("ModLoaderMp");
|
|
if (!isMLMPInstalled() || mlmp == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
mlmp.getDeclaredMethod("handleGUI", Packet100OpenWindow.class).invoke(null, pkt);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|