mirror of
https://github.com/GTNewHorizons/bdlib.git
synced 2026-10-27 14:53:44 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35def010a3 | ||
|
|
911f7aa159 | ||
|
|
3aef519c25 | ||
|
|
6c59b25e2c | ||
|
|
014c1c5e6e | ||
|
|
7fd040e65a | ||
|
|
ece84599f9 | ||
|
|
174af254e8 | ||
|
|
71185838f6 | ||
|
|
f2cdba7800 | ||
|
|
89b54300e3 | ||
|
|
9ee12091e6 | ||
|
|
08ccf07dfb | ||
|
|
382c21f732 | ||
|
|
17e4bf3a2f | ||
|
|
ebe2c1f34a | ||
|
|
fae2825e7b | ||
|
|
b2e138f3cd | ||
|
|
9d897d0663 | ||
|
|
497917185c | ||
|
|
9ff7a75604 | ||
|
|
f8bb1e8fbb | ||
|
|
a530c66680 | ||
|
|
26af828491 | ||
|
|
1c0913d674 | ||
|
|
895cfd9cb6 | ||
|
|
f43dd28e03 | ||
|
|
289f8f7120 | ||
|
|
e7787fb9ca | ||
|
|
58e336f8a9 | ||
|
|
bea6a13896 | ||
|
|
793ceb0024 | ||
|
|
66d9be58c8 | ||
|
|
87d64208c8 | ||
|
|
6f6496c1e3 | ||
|
|
934e984abf | ||
|
|
4900537a82 | ||
|
|
31b5ab9d52 | ||
|
|
8a4ccf7d81 | ||
|
|
429107215f | ||
|
|
0c60d596b6 | ||
|
|
da35094895 | ||
|
|
83d30f12c2 | ||
|
|
8d4484ca18 | ||
|
|
624df87299 | ||
|
|
18b4f19dab |
No files matched your search
+35
-13
@@ -21,21 +21,30 @@ buildscript {
|
||||
apply plugin: 'scala'
|
||||
apply plugin: 'forge'
|
||||
|
||||
version = "1.7.0"
|
||||
file "build.properties" withReader {
|
||||
def prop = new Properties()
|
||||
prop.load(it)
|
||||
ext.config = new ConfigSlurper().parse prop
|
||||
}
|
||||
|
||||
if (project.hasProperty('forgeOverride')) {
|
||||
config.forge.version = forgeOverride
|
||||
}
|
||||
|
||||
if (project.hasProperty('buildnum')) {
|
||||
project.version = project.version + '.' + project.buildnum
|
||||
ext.simpleVersion = "${config.bdlib.version}.${project.buildnum}"
|
||||
} else {
|
||||
project.version = "0-SNAPSHOT"
|
||||
ext.simpleVersion = "${config.bdlib.version}-DEV"
|
||||
}
|
||||
|
||||
version = simpleVersion + '-mc' + config.minecraft.version
|
||||
|
||||
group = "net.bdew"
|
||||
archivesBaseName = "bdlib"
|
||||
ext.versuffix = "mc1710"
|
||||
|
||||
minecraft {
|
||||
version = "1.7.10-10.13.2.1291"
|
||||
replace("BDLIB_VER", project.version)
|
||||
version = "${config.minecraft.version}-${config.forge.version}"
|
||||
replace("BDLIB_VER", simpleVersion.toString())
|
||||
}
|
||||
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
@@ -66,16 +75,18 @@ processResources {
|
||||
}
|
||||
|
||||
task sourceJar(type: Jar) {
|
||||
from sourceSets.main.allSource
|
||||
classifier "sources"
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier "dev"
|
||||
duplicatesStrategy "exclude"
|
||||
}
|
||||
|
||||
jar {
|
||||
appendix = project.versuffix
|
||||
afterEvaluate { project ->
|
||||
// Fudge the inputs of source jars so we get the version after replacements
|
||||
tasks.getByPath(":sourceJar").from(tasks.getByPath(":sourceMainScala").outputs.files)
|
||||
}
|
||||
|
||||
artifacts {
|
||||
@@ -89,10 +100,7 @@ publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
artifact deobfJar
|
||||
|
||||
artifact sourceJar {
|
||||
classifier "sources"
|
||||
}
|
||||
artifact sourceJar
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
@@ -100,4 +108,18 @@ publishing {
|
||||
url "file://var/www/maven"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'curseforge'
|
||||
|
||||
curse {
|
||||
projectId = config.curseforge.id
|
||||
apiKey = project.hasProperty("curseForgeApiKey") ? project.curseForgeApiKey : ""
|
||||
releaseType = 'alpha'
|
||||
|
||||
artifact = jar
|
||||
changelog = project.hasProperty("changelog") ? project.changelog : "No changelog available"
|
||||
|
||||
additionalArtifact deobfJar
|
||||
additionalArtifact sourceJar
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
bdlib.version=1.9.2
|
||||
curseforge.id=70496
|
||||
|
||||
minecraft.version=1.7.10
|
||||
forge.version=10.13.4.1448-1.7.10
|
||||
+1
-1
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-bin.zip
|
||||
@@ -9,6 +9,10 @@ bdlib.multiblock.disabled=Disabled
|
||||
bdlib.multiblock.incomplete=This machine is incomplete, it requires at least:
|
||||
bdlib.multiblock.notconnected=Not connected to a valid machine
|
||||
bdlib.multiblock.toomanyoutputs=Too many outputs connected, unable to attach new connection
|
||||
bdlib.multiblock.tip.module=Can be installed in:
|
||||
bdlib.multiblock.tip.controller=Possible modules:
|
||||
bdlib.multiblock.tip.module.range= * %s (%s - %s)
|
||||
bdlib.multiblock.tip.module.max= * %s (up to %s)
|
||||
|
||||
bdlib.rsmode.always=Always ON
|
||||
bdlib.rsmode.never=Disabled
|
||||
@@ -17,3 +21,10 @@ bdlib.rsmode.rs_off=Disable on redstone
|
||||
|
||||
bdlib.label.empty=Empty
|
||||
|
||||
bdlib.oredistribution.usage=/oredistribution <radius> [<min height>] [<max height>] [--file]
|
||||
bdlib.oredistribution.start1=Checking ore distribution in (%s,%s,%s) to (%s,%s,%s) dim %s
|
||||
bdlib.oredistribution.start2=Server may lag for a while
|
||||
bdlib.oredistribution.entry=%s %s - %s (%s%%)
|
||||
bdlib.oredistribution.warn=%s Warning: %s has multiple variants generated:
|
||||
bdlib.oredistribution.saved=Ore distribution dumped to %s
|
||||
bdlib.oredistribution.error=Failed to save ore distribution dump: %s
|
||||
@@ -0,0 +1,30 @@
|
||||
bdlib.multiblock.face.north=Nord
|
||||
bdlib.multiblock.face.south=Sud
|
||||
bdlib.multiblock.face.east=Est
|
||||
bdlib.multiblock.face.west=Ouest
|
||||
bdlib.multiblock.face.up=Dessus
|
||||
bdlib.multiblock.face.down=Dessous
|
||||
|
||||
bdlib.multiblock.disabled=Désactivé
|
||||
bdlib.multiblock.incomplete=Cette machine est incomplète, elle exige au moins :
|
||||
bdlib.multiblock.notconnected=Pas connecté à une machine valide
|
||||
bdlib.multiblock.toomanyoutputs=Trop de sorties connectées, impossible d'ajouter une nouvelle connexion
|
||||
bdlib.multiblock.tip.module=Peut être installé dans :
|
||||
bdlib.multiblock.tip.controller=Modules possibles:
|
||||
bdlib.multiblock.tip.module.range= * %s (%s - %s)
|
||||
bdlib.multiblock.tip.module.max= * %s (plus de %s)
|
||||
|
||||
bdlib.rsmode.always=Toujours actif
|
||||
bdlib.rsmode.never=Désactivé
|
||||
bdlib.rsmode.rs_on=Activé par redstone
|
||||
bdlib.rsmode.rs_off=Désactivé par redstone
|
||||
|
||||
bdlib.label.empty=Vide
|
||||
|
||||
bdlib.oredistribution.usage=/oredistribution <rayon> [<hauteur mini>] [<hauteur maxi>] [--file]
|
||||
bdlib.oredistribution.start1=Valide la distribution de minerai entre (%s,%s,%s) et (%s,%s,%s) dim %s
|
||||
bdlib.oredistribution.start2=Le server peut ralentir pendantun certain temps
|
||||
bdlib.oredistribution.entry=%s %s - %s (%s%%)
|
||||
bdlib.oredistribution.warn=%s Attention: %s fait produire des variantes multiples :
|
||||
bdlib.oredistribution.saved=Distribution de minerai déposée dans %s
|
||||
bdlib.oredistribution.error=Impossible d'enregistrer la distribution de minerai : %s
|
||||
@@ -0,0 +1,18 @@
|
||||
bdlib.multiblock.face.north=Nord
|
||||
bdlib.multiblock.face.south=Sud
|
||||
bdlib.multiblock.face.east=Est
|
||||
bdlib.multiblock.face.west=Ovest
|
||||
bdlib.multiblock.face.up=Sopra
|
||||
bdlib.multiblock.face.down=Sotto
|
||||
|
||||
bdlib.multiblock.disabled=Disattivo
|
||||
bdlib.multiblock.incomplete=Questa macchina è incompleta, richiede almeno:
|
||||
bdlib.multiblock.notconnected=Non connesso ad una macchina valida
|
||||
bdlib.multiblock.toomanyoutputs=Troppi Output collegati,impossibile inserire una nuova connessione
|
||||
|
||||
bdlib.rsmode.always=Sempre Attivo
|
||||
bdlib.rsmode.never=Disattivo
|
||||
bdlib.rsmode.rs_on=Attivo su Impulso di Pietrarossa
|
||||
bdlib.rsmode.rs_off=Disattivo su Impulso di Pietrarossa
|
||||
|
||||
bdlib.label.empty=Vuoto
|
||||
@@ -10,6 +10,7 @@
|
||||
package net.bdew.lib
|
||||
|
||||
import java.util
|
||||
import java.util.Locale
|
||||
|
||||
import cpw.mods.fml.common.{ICrashCallable, ModAPIManager, ModContainer}
|
||||
|
||||
@@ -20,7 +21,7 @@ object ApiReporter extends ICrashCallable {
|
||||
val mods = new util.ArrayList[ModContainer]
|
||||
val nameLookup = new util.HashMap[String, ModContainer]
|
||||
ModAPIManager.INSTANCE.injectAPIModContainers(mods, nameLookup)
|
||||
(for (mod <- mods.sortBy(_.getModId.toLowerCase)) yield
|
||||
(for (mod <- mods.sortBy(_.getModId.toLowerCase(Locale.US))) yield
|
||||
"\t\t* %s (%s) from %s".format(mod.getModId, mod.getVersion,
|
||||
if (mod.getSource.isDirectory)
|
||||
mod.getSource
|
||||
|
||||
@@ -13,6 +13,7 @@ import cpw.mods.fml.common.Mod.EventHandler
|
||||
import cpw.mods.fml.common.event.{FMLPreInitializationEvent, FMLServerStartingEvent, FMLServerStoppingEvent}
|
||||
import cpw.mods.fml.common.{FMLCommonHandler, Mod}
|
||||
import net.bdew.lib.multiblock.network.NetHandler
|
||||
import net.bdew.lib.tooltip.TooltipHandler
|
||||
import net.minecraft.command.CommandHandler
|
||||
import org.apache.logging.log4j.Logger
|
||||
|
||||
@@ -37,12 +38,16 @@ object BdLib {
|
||||
log.debug("List of loaded APIs: " + ApiReporter.APIs)
|
||||
FMLCommonHandler.instance().registerCrashCallable(ApiReporter)
|
||||
NetHandler.init()
|
||||
if (ev.getSide.isClient) {
|
||||
TooltipHandler.init()
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
def serverStarting(event: FMLServerStartingEvent) {
|
||||
val commandHandler = event.getServer.getCommandManager.asInstanceOf[CommandHandler]
|
||||
commandHandler.registerCommand(new CommandDumpRegistry)
|
||||
commandHandler.registerCommand(CommandDumpRegistry)
|
||||
commandHandler.registerCommand(CommandOreDistribution)
|
||||
onServerStarting.trigger(event)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import net.minecraft.item.ItemStack
|
||||
import net.minecraftforge.fluids.FluidRegistry
|
||||
import net.minecraftforge.oredict.OreDictionary
|
||||
|
||||
class CommandDumpRegistry extends CommandBase {
|
||||
object CommandDumpRegistry extends CommandBase {
|
||||
def getCommandName = "dumpregistry"
|
||||
override def getRequiredPermissionLevel = 2
|
||||
def getCommandUsage(c: ICommandSender) = "dumpregistry"
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib
|
||||
|
||||
import java.io.{BufferedWriter, File, FileWriter}
|
||||
|
||||
import cpw.mods.fml.common.registry.GameData
|
||||
import cpw.mods.fml.relauncher.FMLInjectionData
|
||||
import net.minecraft.command.{CommandBase, ICommandSender, WrongUsageException}
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.util.EnumChatFormatting
|
||||
import net.minecraftforge.oredict.OreDictionary
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
object CommandOreDistribution extends CommandBase {
|
||||
def getCommandName = "oredistribution"
|
||||
override def getRequiredPermissionLevel = 2
|
||||
def getCommandUsage(c: ICommandSender) = "bdlib.oredistribution.usage"
|
||||
|
||||
def safeInt(s: String) =
|
||||
try {
|
||||
s.toInt
|
||||
} catch {
|
||||
case e: NumberFormatException => throw new WrongUsageException("bdlib.oredistribution.usage")
|
||||
}
|
||||
|
||||
def wrapColor(s: String, c: EnumChatFormatting) = c + s + EnumChatFormatting.RESET
|
||||
|
||||
def processCommand(sender: ICommandSender, baseParams: Array[String]) {
|
||||
val (flags, params) = baseParams.partition(_.startsWith("--"))
|
||||
|
||||
if (params.length < 1 || params.length > 3)
|
||||
throw new WrongUsageException(getCommandUsage(sender))
|
||||
|
||||
val (startX, startZ, world) =
|
||||
sender match {
|
||||
case p: EntityPlayerMP => (p.posX.toInt, p.posZ.toInt, p.worldObj)
|
||||
case _ => (0, 0, sender.getEntityWorld)
|
||||
}
|
||||
|
||||
val radius = safeInt(params.head)
|
||||
val minY = if (params.length >= 2) safeInt(params(1)) else 0
|
||||
val maxY = if (params.length >= 3) safeInt(params(2)) else world.getHeight - 1
|
||||
|
||||
if (minY < 0 || radius <= 0 || minY > maxY || maxY > world.getHeight - 1)
|
||||
throw new WrongUsageException(getCommandUsage(sender))
|
||||
|
||||
val toFile = flags.contains("--file")
|
||||
|
||||
// why java, WHY?
|
||||
CommandBase.func_152373_a(sender, this, "bdlib.oredistribution.start1",
|
||||
Array[Integer](startX - radius, minY, startZ - radius, startX + radius, maxY, startZ + radius, world.provider.dimensionId): _*)
|
||||
|
||||
CommandBase.func_152373_a(sender, this, "bdlib.oredistribution.start2")
|
||||
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
val ores = (OreDictionary.getOreNames.filter(x => x.startsWith("ore") || x.startsWith("denseore")) flatMap { name =>
|
||||
val fixedName =
|
||||
if (name.startsWith("ore"))
|
||||
name.substring(3)
|
||||
else if (name.startsWith("denseore"))
|
||||
"Dense " + name.substring(8)
|
||||
else name
|
||||
for (s <- OreDictionary.getOres(name)) yield (s.getItem, s.getItemDamage) -> fixedName
|
||||
}).toMap
|
||||
|
||||
val distribution = mutable.Map.empty[String, Int].withDefaultValue(0)
|
||||
val kinds = mutable.Map.empty[String, Set[(Item, Int)]].withDefaultValue(Set.empty)
|
||||
|
||||
for {
|
||||
x <- startX - radius to startX + radius
|
||||
y <- minY to maxY
|
||||
z <- startZ - radius to startZ + radius
|
||||
if !world.isAirBlock(x, y, z)
|
||||
} {
|
||||
val key = (Item.getItemFromBlock(world.getBlock(x, y, z)), world.getBlockMetadata(x, y, z))
|
||||
for (ore <- ores.get(key)) {
|
||||
distribution(ore) += 1
|
||||
kinds(ore) += key
|
||||
}
|
||||
}
|
||||
|
||||
val total = distribution.values.sum
|
||||
val warnings = kinds.filter(_._2.size > 1)
|
||||
|
||||
if (toFile) {
|
||||
// === OUTPUT TO FILE ===
|
||||
val mcHome = FMLInjectionData.data()(6).asInstanceOf[File] //is there a better way to get this?
|
||||
val dumpFile = new File(mcHome, "ore_distribution.txt")
|
||||
val dumpWriter = new BufferedWriter(new FileWriter(dumpFile))
|
||||
try {
|
||||
dumpWriter.write("Ore distribution report - (%d,%d,%d) to (%d,%d,%d) dim %d".format(
|
||||
startX - radius, minY, startZ - radius, startX + radius, maxY, startZ + radius, world.provider.dimensionId
|
||||
))
|
||||
dumpWriter.newLine()
|
||||
dumpWriter.newLine()
|
||||
if (warnings.nonEmpty) {
|
||||
for ((id, types) <- warnings.toList.sortBy(_._1)) {
|
||||
dumpWriter.write("Warning: %s has multiple variants generated:".format(id))
|
||||
dumpWriter.newLine()
|
||||
for ((item, dmg) <- types) {
|
||||
dumpWriter.write(" - %s@%s".format(GameData.getItemRegistry.getNameForObject(item), dmg))
|
||||
dumpWriter.newLine()
|
||||
}
|
||||
dumpWriter.newLine()
|
||||
}
|
||||
dumpWriter.write("=================")
|
||||
dumpWriter.newLine()
|
||||
dumpWriter.newLine()
|
||||
}
|
||||
for ((id, num) <- distribution.filter(_._2 > 0).toList.sortBy(-_._2)) {
|
||||
dumpWriter.write("%s - %s (%s%%)".format(id, DecFormat.round(num), DecFormat.short(100F * num / total)))
|
||||
dumpWriter.newLine()
|
||||
}
|
||||
CommandBase.func_152373_a(sender, this, "bdlib.oredistribution.saved", dumpFile.getCanonicalPath)
|
||||
} catch {
|
||||
case e: Throwable =>
|
||||
CommandBase.func_152373_a(sender, this, "bdlib.oredistribution.error", e.toString)
|
||||
BdLib.logErrorException("Failed to save ore distribution dump", e)
|
||||
} finally {
|
||||
dumpWriter.close()
|
||||
}
|
||||
} else {
|
||||
// === OUTPUT TO CHAT ===
|
||||
for ((id, types) <- warnings.toList.sortBy(_._1)) {
|
||||
CommandBase.func_152373_a(sender, this, "bdlib.oredistribution.warn",
|
||||
wrapColor(" !", EnumChatFormatting.RED), wrapColor(id, EnumChatFormatting.RED))
|
||||
for ((item, dmg) <- types)
|
||||
CommandBase.func_152373_a(sender, this, wrapColor(" - ", EnumChatFormatting.RED) + GameData.getItemRegistry.getNameForObject(item) + "@" + dmg)
|
||||
}
|
||||
for ((id, num) <- distribution.filter(_._2 > 0).toList.sortBy(-_._2)) {
|
||||
CommandBase.func_152373_a(sender, this, "bdlib.oredistribution.entry",
|
||||
" *", wrapColor(id, EnumChatFormatting.YELLOW),
|
||||
DecFormat.round(num), DecFormat.short(100F * num / total))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ package net.bdew.lib
|
||||
class EventBase[T] extends {
|
||||
var listeners = Seq.empty[T]
|
||||
def listen(x: T) = listeners :+= x
|
||||
def hasListeners = listeners.size > 0
|
||||
def hasListeners = listeners.nonEmpty
|
||||
}
|
||||
|
||||
class Event0 extends EventBase[() => Unit] {
|
||||
|
||||
+56
-24
@@ -9,9 +9,12 @@
|
||||
|
||||
package net.bdew.lib
|
||||
|
||||
import cpw.mods.fml.common.Loader
|
||||
import java.util
|
||||
import java.util.Locale
|
||||
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import cpw.mods.fml.common.versioning.{ArtifactVersion, VersionParser}
|
||||
import cpw.mods.fml.common.versioning.VersionParser
|
||||
import cpw.mods.fml.common.{Loader, ModAPIManager, ModContainer}
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
@@ -22,28 +25,16 @@ import net.minecraftforge.fluids.{Fluid, FluidStack}
|
||||
import net.minecraftforge.oredict.ShapedOreRecipe
|
||||
|
||||
object Misc {
|
||||
@deprecated("Use net.bdew.lib.nbt instead", "bdlib 1.7.0")
|
||||
def iterNbtCompoundList(parent: NBTTagCompound, name: String): Iterable[NBTTagCompound] = {
|
||||
import net.bdew.lib.nbt._
|
||||
parent.getList[NBTTagCompound](name)
|
||||
}
|
||||
|
||||
@deprecated("Use net.bdew.lib.nbt instead", "bdlib 1.7.0")
|
||||
def iterNbtIntArray(parent: NBTTagCompound, name: String): Iterable[Array[Int]] = {
|
||||
import net.bdew.lib.nbt._
|
||||
parent.getList[Array[Int]](name)
|
||||
}
|
||||
|
||||
def getActiveModId = Loader.instance().activeModContainer().getModId
|
||||
def getActiveModId = Option(Loader.instance().activeModContainer().getModId) getOrElse "<UNKNOWN>"
|
||||
|
||||
def toLocal(s: String) = StatCollector.translateToLocal(s)
|
||||
def toLocalF(s: String, params: Any*) = StatCollector.translateToLocal(s).format(params: _*)
|
||||
def hasLocal(s: String) = StatCollector.canTranslate(s)
|
||||
|
||||
def flattenRecipe(pattern: Seq[String], items: Map[Char, AnyRef]) =
|
||||
pattern ++ items.map {
|
||||
pattern ++ items.flatMap {
|
||||
case (k, v) => Seq(new Character(k), v)
|
||||
}.flatten
|
||||
}
|
||||
|
||||
def wrapTag(n: String, f: (NBTTagCompound) => Any)(t: NBTTagCompound) {
|
||||
val p = t.getCompoundTag(n)
|
||||
@@ -69,17 +60,28 @@ object Misc {
|
||||
|
||||
def getBiomeByName(name: String) = BiomeGenBase.getBiomeGenArray.find(x => x != null && x.biomeName == name).orNull
|
||||
|
||||
def haveModVersion(spec: String): Boolean = {
|
||||
val req = VersionParser.parseVersionReference(spec)
|
||||
val modId = req.getLabel
|
||||
private lazy val modLookup = {
|
||||
val mods = new util.ArrayList[ModContainer]
|
||||
val nameLookup = new util.HashMap[String, ModContainer]
|
||||
|
||||
if (!Loader.instance.getIndexedModList.containsKey(modId)) return false
|
||||
nameLookup.putAll(Loader.instance().getIndexedModList)
|
||||
ModAPIManager.INSTANCE.injectAPIModContainers(mods, nameLookup)
|
||||
|
||||
val found: ArtifactVersion = Loader.instance.getIndexedModList.get(modId).getProcessedVersion
|
||||
import scala.collection.JavaConverters._
|
||||
nameLookup.asScala
|
||||
}
|
||||
|
||||
if (found == null || !req.containsVersion(found)) return false
|
||||
def haveModVersion(modId: String) = {
|
||||
val spec = VersionParser.parseVersionReference(modId)
|
||||
modLookup.contains(spec.getLabel) && spec.containsVersion(modLookup(spec.getLabel).getProcessedVersion)
|
||||
}
|
||||
|
||||
return true
|
||||
def getModVersion(modId: String) =
|
||||
modLookup.get(modId) map (_.getVersion)
|
||||
|
||||
def getModVersionString(modId: String): String = {
|
||||
val cont = modLookup.getOrElse(modId, return "NOT FOUND")
|
||||
cont.getModId + " " + cont.getVersion
|
||||
}
|
||||
|
||||
// Because writing this every time is awkward
|
||||
@@ -139,5 +141,35 @@ object Misc {
|
||||
if (f != null) getFluidColor(new FluidStack(f, 1)) else 0xFFFFFF
|
||||
|
||||
lazy val lineSeparator = System.getProperty("line.separator")
|
||||
|
||||
/**
|
||||
* Provides something like java try-with-resources in scala
|
||||
*/
|
||||
def withAutoClose[T <: AutoCloseable, R](o: T)(f: T => R): R = {
|
||||
val res = try {
|
||||
f(o)
|
||||
} catch {
|
||||
case t1: Throwable =>
|
||||
if (o != null) {
|
||||
try {
|
||||
o.close()
|
||||
} catch {
|
||||
case t2: Throwable =>
|
||||
t1.addSuppressed(t2)
|
||||
}
|
||||
}
|
||||
throw t1
|
||||
}
|
||||
if (o != null)
|
||||
o.close()
|
||||
res
|
||||
}
|
||||
|
||||
def iconName(domain: String, name: String, path: String*) =
|
||||
if (path.isEmpty)
|
||||
"%s:%s".format(domain, name).toLowerCase(Locale.US)
|
||||
else
|
||||
"%s:%s/%s".format(domain, name, path.mkString("/")).toLowerCase(Locale.US)
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.async
|
||||
|
||||
import scala.concurrent.{Future, Promise}
|
||||
|
||||
object Async {
|
||||
def inOtherThread[T](f: => T) = {
|
||||
val p = Promise[T]()
|
||||
val t = new Thread(new Runnable {
|
||||
override def run(): Unit =
|
||||
try {
|
||||
p.success(f)
|
||||
} catch {
|
||||
case t: Throwable => p.failure(t)
|
||||
}
|
||||
})
|
||||
t.start()
|
||||
p.future
|
||||
}
|
||||
|
||||
def inServerThread[T](f: => T) = Future(f)(ServerTickExecutionContext)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.async
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent
|
||||
import net.bdew.lib.BdLib
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
object ServerTickExecutionContext extends ExecutionContext {
|
||||
private val queue = mutable.Queue.empty[Runnable]
|
||||
|
||||
FMLCommonHandler.instance.bus.register(this)
|
||||
|
||||
BdLib.logDebug("Installed ServerTickExecutionContext")
|
||||
|
||||
private def getNextBatch = this.synchronized {
|
||||
if (queue.nonEmpty) {
|
||||
val res = queue.toList
|
||||
queue.clear()
|
||||
res
|
||||
} else List.empty
|
||||
}
|
||||
|
||||
override def execute(runnable: Runnable): Unit =
|
||||
this.synchronized {
|
||||
queue += runnable
|
||||
}
|
||||
|
||||
override def reportFailure(cause: Throwable): Unit =
|
||||
BdLib.logErrorException("Error in execution context", cause)
|
||||
|
||||
def doSingleLoop(): Unit = {
|
||||
for (r <- getNextBatch) {
|
||||
try {
|
||||
r.run()
|
||||
} catch {
|
||||
case t: Throwable => reportFailure(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
def onTick(ev: ServerTickEvent): Unit = doSingleLoop()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.block
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.item.ItemBlock
|
||||
|
||||
/**
|
||||
* If defined on a block - defines a custom ItemBlock class that will be used when registering
|
||||
* Supported by BlockManager and Machine
|
||||
*/
|
||||
trait HasItemBlock extends Block {
|
||||
def ItemBlockClass: Class[_ <: ItemBlock]
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.block
|
||||
|
||||
import java.util
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.{ItemBlock, ItemStack}
|
||||
|
||||
trait BlockTooltip extends Block with HasItemBlock {
|
||||
override val ItemBlockClass: Class[_ <: ItemBlock] = classOf[ItemBlockTooltip]
|
||||
def getTooltip(stack: ItemStack, player: EntityPlayer, advanced: Boolean): List[String]
|
||||
}
|
||||
|
||||
class ItemBlockTooltip(b: Block) extends ItemBlock(b) {
|
||||
override def addInformation(stack: ItemStack, player: EntityPlayer, list: util.List[_], advanced: Boolean): Unit = {
|
||||
import scala.collection.JavaConversions._
|
||||
if (b.isInstanceOf[BlockTooltip])
|
||||
list.asInstanceOf[util.List[String]].addAll(b.asInstanceOf[BlockTooltip].getTooltip(stack, player, advanced))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.block
|
||||
|
||||
import java.util
|
||||
|
||||
import net.bdew.lib.nbt.NBT
|
||||
import net.bdew.lib.tile.TileExtended
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.MovingObjectPosition
|
||||
import net.minecraft.world.World
|
||||
|
||||
/**
|
||||
* Mixin for blocks to keep their data when broken
|
||||
* Must have a TileEntity that extends TileKeepData
|
||||
*/
|
||||
trait BlockKeepData extends Block with HasItemBlock {
|
||||
this: HasTE[_ <: TileKeepData] =>
|
||||
|
||||
override val ItemBlockClass: Class[_ <: ItemBlockKeepData] = classOf[ItemBlockKeepData]
|
||||
|
||||
def getSavedBlock(world: World, x: Int, y: Int, z: Int, metadata: Int) = {
|
||||
val stack = new ItemStack(getItemDropped(metadata, world.rand, 0), 1, damageDropped(metadata))
|
||||
getTE(world, x, y, z).saveToItem(stack)
|
||||
stack
|
||||
}
|
||||
|
||||
override def getDrops(world: World, x: Int, y: Int, z: Int, metadata: Int, fortune: Int): util.ArrayList[ItemStack] = {
|
||||
val drops = new util.ArrayList[ItemStack]()
|
||||
drops.add(getSavedBlock(world, x, y, z, metadata))
|
||||
drops
|
||||
}
|
||||
|
||||
override def removedByPlayer(world: World, player: EntityPlayer, x: Int, y: Int, z: Int, willHarvest: Boolean): Boolean =
|
||||
if (willHarvest)
|
||||
true
|
||||
else
|
||||
super.removedByPlayer(world, player, x, y, z, willHarvest)
|
||||
|
||||
override def harvestBlock(world: World, player: EntityPlayer, x: Int, y: Int, z: Int, meta: Int): Unit = {
|
||||
super.harvestBlock(world, player, x, y, z, meta)
|
||||
world.setBlockToAir(x, y, z)
|
||||
}
|
||||
|
||||
override def getPickBlock(target: MovingObjectPosition, world: World, x: Int, y: Int, z: Int, player: EntityPlayer): ItemStack = {
|
||||
getSavedBlock(world, x, y, z, world.getBlockMetadata(x, y, z))
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for special actions on placing
|
||||
* ItemStack might or might not contain actual data
|
||||
* Called with the TE created and added to world, after onBlockPlacedBy & co
|
||||
*/
|
||||
def restoreTileEntity(world: World, x: Int, y: Int, z: Int, is: ItemStack, player: EntityPlayer) = getTE(world, x, y, z).loadFromItem(is)
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin for tile entities to keep their data when broken
|
||||
* Block class has to extend BlockKeepData
|
||||
*/
|
||||
trait TileKeepData extends TileExtended {
|
||||
/**
|
||||
* Override to modify data that will be stored in an item
|
||||
* @param t Automatically serialized data
|
||||
* @return Modified serialized data
|
||||
*/
|
||||
def afterTileBreakSave(t: NBTTagCompound) = t
|
||||
|
||||
/**
|
||||
* Override to modify data that will be load from an item
|
||||
* After the tile entity is fully constructed and added to world
|
||||
* @param t Automatically serialized data
|
||||
* @return Modified serialized data
|
||||
*/
|
||||
def beforeTileBreakLoad(t: NBTTagCompound) = t
|
||||
|
||||
final def saveToItem(is: ItemStack): Unit = {
|
||||
if (!is.hasTagCompound) is.setTagCompound(new NBTTagCompound)
|
||||
is.getTagCompound.setTag("data", afterTileBreakSave(NBT.from(persistSave.trigger)))
|
||||
}
|
||||
|
||||
final def loadFromItem(is: ItemStack): Unit = {
|
||||
if (is.hasTagCompound && is.getTagCompound.hasKey("data")) {
|
||||
persistLoad.trigger(beforeTileBreakLoad(is.getTagCompound.getCompoundTag("data")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom ItemBlock that handles loading data to the Tile Entity
|
||||
*/
|
||||
class ItemBlockKeepData(b: Block) extends ItemBlockTooltip(b) {
|
||||
override def placeBlockAt(stack: ItemStack, player: EntityPlayer, world: World, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float, metadata: Int): Boolean = {
|
||||
if (super.placeBlockAt(stack, player, world, x, y, z, side, hitX, hitY, hitZ, metadata)) {
|
||||
if (!world.isRemote && b.isInstanceOf[BlockKeepData])
|
||||
b.asInstanceOf[BlockKeepData].restoreTileEntity(world, x, y, z, stack, player)
|
||||
true
|
||||
} else false
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
trait NamedBlock extends Block {
|
||||
def name: String
|
||||
}
|
||||
@@ -25,6 +27,6 @@ class SimpleBlock(val name: String, material: Material) extends Block(material)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def registerBlockIcons(reg: IIconRegister) {
|
||||
blockIcon = reg.registerIcon(modId + ":" + name.toLowerCase)
|
||||
blockIcon = reg.registerIcon(Misc.iconName(modId, name))
|
||||
}
|
||||
}
|
||||
@@ -9,19 +9,27 @@
|
||||
|
||||
package net.bdew.lib.config
|
||||
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.{HasTE, NamedBlock}
|
||||
import net.bdew.lib.block.{HasItemBlock, HasTE, NamedBlock}
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import net.minecraft.item.{ItemBlock, Item, ItemStack}
|
||||
import net.minecraft.item.{ItemBlock, ItemStack}
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
|
||||
class BlockManager(creativeTab: CreativeTabs) {
|
||||
def regBlock[T <: NamedBlock](block: T): T = regBlock(block, block.name)
|
||||
|
||||
def regBlock[T <: NamedBlock](block: T, itemClass: Class[_ <: ItemBlock]): T = regBlock(block, block.name, itemClass)
|
||||
def regSpecial[T <: NamedBlock](block: T, addStack: Boolean = false, skipTileEntityReg: Boolean = false): T =
|
||||
regBlock(block, block.name, addStack, skipTileEntityReg)
|
||||
|
||||
def regBlock[T <: Block](block: T, name: String, addStack: Boolean = false, skipTileEntityReg: Boolean = false): T = {
|
||||
val itemClass: Class[_ <: ItemBlock] = if (block.isInstanceOf[HasItemBlock])
|
||||
block.asInstanceOf[HasItemBlock].ItemBlockClass
|
||||
else
|
||||
classOf[ItemBlock]
|
||||
|
||||
def regBlock[T <: Block](block: T, name: String, itemClass: Class[_ <: ItemBlock] = classOf[ItemBlock], addStack: Boolean = false): T = {
|
||||
GameRegistry.registerBlock(block, itemClass, name)
|
||||
|
||||
block.setCreativeTab(creativeTab)
|
||||
@@ -29,12 +37,21 @@ class BlockManager(creativeTab: CreativeTabs) {
|
||||
if (addStack)
|
||||
GameRegistry.registerCustomItemStack(name, new ItemStack(block))
|
||||
|
||||
if (block.isInstanceOf[HasTE[_]])
|
||||
if (block.isInstanceOf[HasTE[_]] && !skipTileEntityReg)
|
||||
GameRegistry.registerTileEntity(block.asInstanceOf[HasTE[_]].TEClass,
|
||||
"%s.%s".format(Misc.getActiveModId, name))
|
||||
|
||||
return block
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a legacy TE name->class mapping. Stolen from GameRegistry.registerTileEntityWithAlternatives
|
||||
*/
|
||||
def registerLegacyTileEntity(name: String, cls: Class[_ <: TileEntity]): Unit = {
|
||||
val teMappings: java.util.Map[String, Class[_]] = ObfuscationReflectionHelper.getPrivateValue(classOf[TileEntity], null, "field_" + "145855_i", "nameToClassMap")
|
||||
if (!teMappings.containsKey(name))
|
||||
teMappings.put(name, cls)
|
||||
}
|
||||
|
||||
def load() {}
|
||||
}
|
||||
@@ -9,8 +9,11 @@
|
||||
|
||||
package net.bdew.lib.config
|
||||
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.gui.{GuiHandler, GuiProvider}
|
||||
import net.bdew.lib.machine.Machine
|
||||
import net.bdew.lib.multiblock.MachineCore
|
||||
import net.bdew.lib.multiblock.block.BlockModule
|
||||
import net.bdew.lib.recipes.gencfg.ConfigSection
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
|
||||
@@ -25,5 +28,27 @@ class MachineManager(val tuning: ConfigSection, guiHandler: GuiHandler, creative
|
||||
}
|
||||
return machine
|
||||
}
|
||||
|
||||
def load() {}
|
||||
}
|
||||
|
||||
trait MachineManagerMultiblock extends MachineManager {
|
||||
var controllers = Set.empty[MachineCore]
|
||||
|
||||
override def registerMachine[R <: Machine[_]](machine: R): R = {
|
||||
super.registerMachine(machine)
|
||||
if (machine.enabled) {
|
||||
Misc.asInstanceOpt(machine, classOf[MachineCore]) foreach { controllerMachine =>
|
||||
controllers += controllerMachine
|
||||
controllerMachine.getController.machine = controllerMachine
|
||||
}
|
||||
}
|
||||
machine
|
||||
}
|
||||
|
||||
def getMachinesForBlock(b: BlockModule[_]): Map[MachineCore, (Int, Int)] = {
|
||||
(for (machine <- controllers; max <- machine.modules.get(b.kind)) yield {
|
||||
machine ->(machine.required.getOrElse(b.kind, 0), max)
|
||||
}).toMap
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,11 @@ package net.bdew.lib.covers
|
||||
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.HasTE
|
||||
import net.bdew.lib.block.{BlockRef, HasTE}
|
||||
import net.bdew.lib.items.ItemUtils
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP}
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.IIcon
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
@@ -23,53 +24,101 @@ trait BlockCoverable[T <: TileCoverable] extends HasTE[T] {
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getRenderType = CoverRenderer.id
|
||||
|
||||
private def getCoverItem(w: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection): Option[(ItemCover, ItemStack, TileCoverable)] = {
|
||||
val te = getTE(w, x, y, z)
|
||||
for {
|
||||
coverStack <- Option(te.covers(side).value)
|
||||
coverItemMaybe <- Option(coverStack.getItem)
|
||||
coverItem <- Misc.asInstanceOpt(coverItemMaybe, classOf[ItemCover])
|
||||
} yield (coverItem, coverStack, te)
|
||||
}
|
||||
|
||||
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, face: Int, xOffs: Float, yOffs: Float, zOffs: Float): Boolean = {
|
||||
val te = getTE(world, x, y, z)
|
||||
val side = Misc.forgeDirection(face)
|
||||
|
||||
// Shift+RightClick with empty hand should remove cover
|
||||
if (player.getCurrentEquippedItem == null && player.isSneaking) {
|
||||
for (cover <- Option(te.covers(side).value)) {
|
||||
for {
|
||||
cover <- Option(te.covers(side).value)
|
||||
coverItem <- Misc.asInstanceOpt(cover.getItem, classOf[ItemCover])
|
||||
} {
|
||||
if (!world.isRemote) {
|
||||
te.covers(side) := null
|
||||
te.onCoversChanged()
|
||||
ItemUtils.dropItemToPlayer(world, player, cover)
|
||||
coverChanged(world, x, y, z, side)
|
||||
ItemUtils.dropItemToPlayer(world, player, coverItem.onRemove(cover))
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// If held item is cover - try to install it
|
||||
for {
|
||||
activeStack <- Option(player.getCurrentEquippedItem)
|
||||
activeItem <- Option(activeStack.getItem)
|
||||
coverItem <- Misc.asInstanceOpt(activeItem, classOf[ItemCover])
|
||||
if te.isValidCover(side, activeStack) && coverItem.isValidTile(te, activeStack)
|
||||
} {
|
||||
if (!world.isRemote) {
|
||||
for (cover <- Option(te.covers(side).value))
|
||||
ItemUtils.throwItemAt(world, te.xCoord + side.offsetX, te.yCoord + side.offsetY, te.zCoord + side.offsetZ, cover.copy())
|
||||
if (!world.isRemote && player.isInstanceOf[EntityPlayerMP]) {
|
||||
for {
|
||||
oldCover <- Option(te.covers(side).value)
|
||||
oldItem <- Misc.asInstanceOpt(oldCover.getItem, classOf[ItemCover])
|
||||
} {
|
||||
ItemUtils.throwItemAt(world, te.xCoord + side.offsetX, te.yCoord + side.offsetY, te.zCoord + side.offsetZ, oldItem.onRemove(oldCover))
|
||||
}
|
||||
|
||||
te.covers(side) := activeStack.splitStack(1)
|
||||
te.covers(side) := coverItem.onInstall(te, side, activeStack.splitStack(1), player.asInstanceOf[EntityPlayerMP])
|
||||
|
||||
if (activeStack.stackSize <= 0)
|
||||
player.inventory.setInventorySlotContents(player.inventory.currentItem, null)
|
||||
|
||||
if (activeStack.stackSize <= 0) player.inventory.setInventorySlotContents(player.inventory.currentItem, null)
|
||||
te.onCoversChanged()
|
||||
coverChanged(world, x, y, z, side)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// If has cover - let it handle the click
|
||||
for ((item, stack, te) <- getCoverItem(world, x, y, z, side)) {
|
||||
if (item.clickCover(te, side, stack, player)) return true
|
||||
}
|
||||
|
||||
super.onBlockActivated(world, x, y, z, player, face, xOffs, yOffs, zOffs)
|
||||
}
|
||||
|
||||
override def canProvidePower = true
|
||||
|
||||
override def isProvidingWeakPower(w: IBlockAccess, x: Int, y: Int, z: Int, side: Int): Int = {
|
||||
val direction = Misc.forgeDirection(side).getOpposite
|
||||
for ((item, stack, te) <- getCoverItem(w, x, y, z, direction)) {
|
||||
if (item.isEmittingSignal(te, direction, stack)) return 15
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
def coverChanged(w: World, x: Int, y: Int, z: Int, side: ForgeDirection): Unit = {
|
||||
val pos = BlockRef(x, y, z).neighbour(side)
|
||||
w.notifyBlockOfNeighborChange(pos.x, pos.y, pos.z, pos.block(w).orNull)
|
||||
}
|
||||
|
||||
def getCoverIcon(w: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection): Option[IIcon] =
|
||||
for {
|
||||
coverStack <- Option(getTE(w, x, y, z).covers(side).value)
|
||||
coverItemMaybe <- Option(coverStack.getItem)
|
||||
coverItem <- Misc.asInstanceOpt(coverItemMaybe, classOf[ItemCover])
|
||||
} yield coverItem.getCoverIcon(coverStack)
|
||||
for ((item, stack, te) <- getCoverItem(w, x, y, z, side))
|
||||
yield item.getCoverIcon(te, side, stack)
|
||||
|
||||
override def breakBlock(world: World, x: Int, y: Int, z: Int, block: Block, meta: Int) {
|
||||
if (!world.isRemote)
|
||||
for ((dir, covOpt) <- getTE(world, x, y, z).covers; cover <- Option(covOpt.value))
|
||||
ItemUtils.throwItemAt(world, x, y, z, cover)
|
||||
if (!world.isRemote) {
|
||||
val te = getTE(world, x, y, z)
|
||||
for {
|
||||
(dir, covOpt) <- te.covers
|
||||
cover <- Option(covOpt.value)
|
||||
item <- Misc.asInstanceOpt(cover.getItem, classOf[ItemCover])
|
||||
} {
|
||||
te.covers(dir) := null
|
||||
ItemUtils.throwItemAt(world, x, y, z, item.onRemove(cover))
|
||||
coverChanged(world, x, y, z, dir)
|
||||
}
|
||||
}
|
||||
super.breakBlock(world, x, y, z, block, meta)
|
||||
}
|
||||
}
|
||||
@@ -23,12 +23,13 @@ object CoverRenderer extends BaseBlockRenderHandler {
|
||||
|
||||
override def renderWorldBlock(world: IBlockAccess, x: Int, y: Int, z: Int, block: Block, modelId: Int, renderer: RenderBlocks) = {
|
||||
renderer.renderStandardBlock(block, x, y, z)
|
||||
for {
|
||||
blockCov <- Misc.asInstanceOpt(block, classOf[BlockCoverable[_]])
|
||||
face <- ForgeDirection.VALID_DIRECTIONS
|
||||
icon <- blockCov.getCoverIcon(world, x, y, z, face)
|
||||
if block.shouldSideBeRendered(world, x + face.offsetX, y + face.offsetY, z + face.offsetZ, face.ordinal())
|
||||
} ConnectedHelper.draw(face, 8).doDraw(ConnectedHelper.Vec3F(x, y, z), icon)
|
||||
if (!renderer.hasOverrideBlockTexture)
|
||||
for {
|
||||
blockCov <- Misc.asInstanceOpt(block, classOf[BlockCoverable[_]])
|
||||
face <- ForgeDirection.VALID_DIRECTIONS
|
||||
icon <- blockCov.getCoverIcon(world, x, y, z, face)
|
||||
if block.shouldSideBeRendered(world, x + face.offsetX, y + face.offsetY, z + face.offsetZ, face.ordinal())
|
||||
} ConnectedHelper.draw(face, 8).doDraw(ConnectedHelper.Vec3F(x, y, z), icon)
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
@@ -9,23 +9,74 @@
|
||||
|
||||
package net.bdew.lib.covers
|
||||
|
||||
import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP}
|
||||
import net.minecraft.item.{Item, ItemStack}
|
||||
import net.minecraft.util.IIcon
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
trait ItemCover extends Item {
|
||||
/**
|
||||
* @return true if tickCover should be called
|
||||
*/
|
||||
def isCoverTicking: Boolean
|
||||
|
||||
/**
|
||||
* @param te Host TileEntity
|
||||
* @param side Side the cover is installed on
|
||||
* @param cover Cover ItemStack
|
||||
* @return Icon to render, MUST be on terrain sprite sheet (0), not item!
|
||||
*/
|
||||
def getCoverIcon(stack: ItemStack): IIcon
|
||||
def getCoverIcon(te: TileCoverable, side: ForgeDirection, cover: ItemStack): IIcon
|
||||
|
||||
/**
|
||||
* Perform tick, called on server only
|
||||
* @param te Host TileEntity
|
||||
* @param side Side the cover is installed on
|
||||
* @param cover Cover ItemStack
|
||||
*/
|
||||
def tickCover(te: TileCoverable, side: ForgeDirection, cover: ItemStack)
|
||||
def tickCover(te: TileCoverable, side: ForgeDirection, cover: ItemStack): Unit = {}
|
||||
|
||||
/**
|
||||
* Checks if this cover can be installed on a specific TE
|
||||
* @param te Potential host TileEntity
|
||||
* @param cover Cover ItemStack
|
||||
* @return true if can be installed
|
||||
*/
|
||||
def isValidTile(te: TileCoverable, cover: ItemStack): Boolean
|
||||
|
||||
/**
|
||||
* Handle click on covered side - called on both client and server
|
||||
* @param te Host TileEntity
|
||||
* @param side Side the cover is installed on
|
||||
* @param cover Cover ItemStack
|
||||
* @param player Player clicking the cover
|
||||
* @return true if click was handled by cover
|
||||
*/
|
||||
def clickCover(te: TileCoverable, side: ForgeDirection, cover: ItemStack, player: EntityPlayer): Boolean = false
|
||||
|
||||
/**
|
||||
* Check if cover is emitting RS signal
|
||||
* @param te Host TileEntity
|
||||
* @param side Side the cover is installed on
|
||||
* @param cover Cover ItemStack
|
||||
* @return true if cover is emitting RS signal
|
||||
*/
|
||||
def isEmittingSignal(te: TileCoverable, side: ForgeDirection, cover: ItemStack): Boolean = false
|
||||
|
||||
/**
|
||||
* Called when cover is installed on a block - called only on server
|
||||
* @param te Host TileEntity
|
||||
* @param side Side the cover is installed on
|
||||
* @param cover Cover ItemStack - do not modify!
|
||||
* @param player Player entity doing the installation
|
||||
* @return cover ItemStack - copy if modified
|
||||
*/
|
||||
def onInstall(te:TileCoverable, side: ForgeDirection, cover: ItemStack, player: EntityPlayerMP): ItemStack = cover
|
||||
|
||||
/**
|
||||
* Called when cover is removed from block or block is destroyed - called only on server
|
||||
* @param cover Cover ItemStack - do not modify!
|
||||
* @return cover ItemStack - copy if modified
|
||||
*/
|
||||
def onRemove(cover: ItemStack): ItemStack = cover
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
package net.bdew.lib.covers
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.data.DataSlotItemStack
|
||||
import net.bdew.lib.data.base.{TileDataSlots, UpdateKind}
|
||||
@@ -17,7 +19,7 @@ import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
trait TileCoverable extends TileDataSlots {
|
||||
val covers = (ForgeDirection.VALID_DIRECTIONS map { x =>
|
||||
x -> DataSlotItemStack("cover_" + x.toString.toLowerCase, this).setUpdate(UpdateKind.SAVE, UpdateKind.WORLD, UpdateKind.RENDER)
|
||||
x -> DataSlotItemStack("cover_" + x.toString.toLowerCase(Locale.US), this).setUpdate(UpdateKind.SAVE, UpdateKind.WORLD, UpdateKind.RENDER)
|
||||
}).toMap
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ case class DataSlotFluidOption(name: String, parent: DataSlotContainer) extends
|
||||
setUpdate(UpdateKind.SAVE, UpdateKind.GUI)
|
||||
|
||||
override def save(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
value map { x => t.setString(name, x.getName) }
|
||||
value foreach { x => t.setString(name, x.getName) }
|
||||
}
|
||||
|
||||
override def load(t: NBTTagCompound, kind: UpdateKind.Value): Unit = {
|
||||
|
||||
@@ -29,8 +29,8 @@ case class DataSlotGameProfile(name: String, parent: DataSlotContainer) extends
|
||||
|
||||
override def save(t: NBTTagCompound, kind: UpdateKind.Value) = {
|
||||
if (value != null) {
|
||||
Option(value.getId) map (id => t.setString(name + "_uid", id.toString))
|
||||
Option(value.getName) filterNot (name => StringUtils.isBlank(name)) map (name => t.setString(name + "_name", name))
|
||||
Option(value.getId) foreach (id => t.setString(name + "_uid", id.toString))
|
||||
Option(value.getName) filterNot (name => StringUtils.isBlank(name)) foreach (name => t.setString(name + "_name", name))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ package net.bdew.lib.data
|
||||
|
||||
import net.bdew.lib.data.base.{DataSlot, DataSlotContainer, UpdateKind}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraftforge.fluids.{FluidStack, FluidTank, IFluidTank}
|
||||
import net.minecraftforge.fluids._
|
||||
|
||||
abstract class DataSlotTankBase(sz: Int) extends FluidTank(sz) with IFluidTank with DataSlot {
|
||||
var oldStack: FluidStack = null
|
||||
@@ -69,11 +69,11 @@ abstract class DataSlotTankBase(sz: Int) extends FluidTank(sz) with IFluidTank w
|
||||
|
||||
case class DataSlotTank(name: String, parent: DataSlotContainer, size: Int) extends DataSlotTankBase(size)
|
||||
|
||||
case class DataSlotTankRestricted(name: String, parent: DataSlotContainer, var size: Int, fluidID: Int) extends DataSlotTankBase(size) {
|
||||
def fill(amount: Int, doFill: Boolean) = super.fill(new FluidStack(fluidID, amount), doFill)
|
||||
case class DataSlotTankRestricted(name: String, parent: DataSlotContainer, var size: Int, filterFluid: Fluid) extends DataSlotTankBase(size) {
|
||||
def fill(amount: Int, doFill: Boolean) = super.fill(new FluidStack(filterFluid, amount), doFill)
|
||||
|
||||
override def fill(resource: FluidStack, doFill: Boolean): Int = {
|
||||
if ((resource != null) && (resource.fluidID != fluidID)) return 0
|
||||
if ((resource != null) && (resource.getFluid != filterFluid)) return 0
|
||||
return super.fill(resource, doFill)
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ trait TileDataSlots extends TileExtended with DataSlotContainer {
|
||||
if (getWorldObj != null) {
|
||||
if (slot.updateKind.contains(UpdateKind.GUI))
|
||||
lastChange = getWorldObj.getTotalWorldTime
|
||||
if (slot.updateKind.contains(UpdateKind.WORLD))
|
||||
if (!getWorldObj.isRemote && slot.updateKind.contains(UpdateKind.WORLD))
|
||||
getWorldObj.markBlockForUpdate(xCoord, yCoord, zCoord)
|
||||
if (slot.updateKind.contains(UpdateKind.SAVE))
|
||||
getWorldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this)
|
||||
|
||||
@@ -56,7 +56,7 @@ abstract class BaseScreen(cont: Container, xSz: Int, ySz: Int) extends GuiContai
|
||||
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
if (tip.size > 0)
|
||||
if (tip.nonEmpty)
|
||||
drawHoveringText(tip, x, y, getFontRenderer)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.helpers
|
||||
|
||||
import net.minecraft.util._
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
class RichChatComponent(v: IChatComponent) {
|
||||
def &(that: IChatComponent) = v.appendSibling(that)
|
||||
|
||||
private def applyStyle(f: ChatStyle => Unit) = {
|
||||
f(v.getChatStyle)
|
||||
v
|
||||
}
|
||||
|
||||
def setColor(c: EnumChatFormatting) = applyStyle(_.setColor(c))
|
||||
def setBold(b: Boolean) = applyStyle(_.setBold(b))
|
||||
def setItalic(b: Boolean) = applyStyle(_.setItalic(b))
|
||||
def setObfuscated(b: Boolean) = applyStyle(_.setObfuscated(b))
|
||||
def setStrikethrough(b: Boolean) = applyStyle(_.setStrikethrough(b))
|
||||
def setUnderlined(b: Boolean) = applyStyle(_.setUnderlined(b))
|
||||
|
||||
}
|
||||
|
||||
object ChatHelper {
|
||||
|
||||
object Color {
|
||||
val BLACK = EnumChatFormatting.BLACK
|
||||
val DARK_BLUE = EnumChatFormatting.DARK_BLUE
|
||||
val DARK_GREEN = EnumChatFormatting.DARK_GREEN
|
||||
val DARK_AQUA = EnumChatFormatting.DARK_AQUA
|
||||
val DARK_RED = EnumChatFormatting.DARK_RED
|
||||
val DARK_PURPLE = EnumChatFormatting.DARK_PURPLE
|
||||
val GOLD = EnumChatFormatting.GOLD
|
||||
val GRAY = EnumChatFormatting.GRAY
|
||||
val DARK_GRAY = EnumChatFormatting.DARK_GRAY
|
||||
val BLUE = EnumChatFormatting.BLUE
|
||||
val GREEN = EnumChatFormatting.GREEN
|
||||
val AQUA = EnumChatFormatting.AQUA
|
||||
val RED = EnumChatFormatting.RED
|
||||
val LIGHT_PURPLE = EnumChatFormatting.LIGHT_PURPLE
|
||||
val YELLOW = EnumChatFormatting.YELLOW
|
||||
val WHITE = EnumChatFormatting.WHITE
|
||||
}
|
||||
|
||||
implicit def str2chat(s: String): ChatComponentText = new ChatComponentText(s)
|
||||
implicit def str2rich(s: String): RichChatComponent = new RichChatComponent(new ChatComponentText(s))
|
||||
implicit def pimpIChatComponent(v: IChatComponent): RichChatComponent = new RichChatComponent(v)
|
||||
|
||||
def C(s: String) = new ChatComponentText(s)
|
||||
def L(s: String, params: IChatComponent*) = new ChatComponentTranslation(s, params: _*)
|
||||
}
|
||||
@@ -24,6 +24,6 @@ class SimpleItem(val name: String) extends Item with NamedItem {
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def registerIcons(reg: IIconRegister) {
|
||||
itemIcon = reg.registerIcon(modId + ":" + name.toLowerCase)
|
||||
itemIcon = reg.registerIcon(Misc.iconName(modId, name))
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,11 @@ package net.bdew.lib.machine
|
||||
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.HasTE
|
||||
import net.bdew.lib.block.{HasItemBlock, HasTE}
|
||||
import net.bdew.lib.recipes.gencfg.ConfigSection
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import net.minecraft.item.ItemBlock
|
||||
|
||||
abstract class Machine[T <: Block](val name: String, blockConstruct: => T) {
|
||||
var block: T = null.asInstanceOf[T]
|
||||
@@ -24,7 +25,14 @@ abstract class Machine[T <: Block](val name: String, blockConstruct: => T) {
|
||||
|
||||
def regBlock(creativeTab: CreativeTabs) {
|
||||
block = blockConstruct
|
||||
GameRegistry.registerBlock(block, name)
|
||||
|
||||
val itemClass: Class[_ <: ItemBlock] = if (block.isInstanceOf[HasItemBlock])
|
||||
block.asInstanceOf[HasItemBlock].ItemBlockClass
|
||||
else
|
||||
classOf[ItemBlock]
|
||||
|
||||
GameRegistry.registerBlock(block, itemClass, name)
|
||||
|
||||
block.setCreativeTab(creativeTab)
|
||||
if (block.isInstanceOf[HasTE[_]]) {
|
||||
GameRegistry.registerTileEntity(block.asInstanceOf[HasTE[_]].TEClass, "%s.%s".format(modId, name))
|
||||
|
||||
@@ -9,11 +9,16 @@
|
||||
|
||||
package net.bdew.lib.multiblock
|
||||
|
||||
import net.bdew.lib.machine.Machine
|
||||
import net.bdew.lib.multiblock.block.BlockController
|
||||
import net.bdew.lib.recipes.gencfg.{ConfigSection, EntryDouble}
|
||||
|
||||
trait MachineCore {
|
||||
trait MachineCore extends {
|
||||
this: Machine[_ <: BlockController[_]] =>
|
||||
var tuning: ConfigSection
|
||||
|
||||
def getController: BlockController[_] = block
|
||||
|
||||
def cfgSectionToMap(name: String) = tuning.getSection(name).map({
|
||||
case (n, EntryDouble(v)) => n -> v.toInt
|
||||
case (n, x) => sys.error("Invalid config value in section %s%s.%s = %s".format(tuning.pfx, name, n, x))
|
||||
|
||||
@@ -41,7 +41,7 @@ object Tools {
|
||||
val seen = mutable.Set.empty[BlockRef]
|
||||
val queue = mutable.Queue.empty[BlockRef]
|
||||
queue ++= getConnectedNeighbours(world, core, core, seen)
|
||||
while (queue.size > 0) {
|
||||
while (queue.nonEmpty) {
|
||||
val current = queue.dequeue()
|
||||
seen.add(current)
|
||||
queue ++= getConnectedNeighbours(world, core, current, seen)
|
||||
|
||||
@@ -9,17 +9,22 @@
|
||||
|
||||
package net.bdew.lib.multiblock.block
|
||||
|
||||
import net.bdew.lib.block.{BlockRef, HasTE}
|
||||
import net.bdew.lib.multiblock.ResourceProvider
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.{BlockRef, BlockTooltip, HasTE}
|
||||
import net.bdew.lib.multiblock.tile.TileController
|
||||
import net.bdew.lib.multiblock.{MachineCore, ResourceProvider}
|
||||
import net.bdew.lib.render.connected.ConnectedTextureBlock
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.EnumChatFormatting
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
|
||||
abstract class BlockController[T <: TileController](val name: String, material: Material, val TEClass: Class[T])
|
||||
extends Block(material) with HasTE[T] with ConnectedTextureBlock {
|
||||
extends Block(material) with HasTE[T] with ConnectedTextureBlock with BlockTooltip {
|
||||
|
||||
var machine: MachineCore = null
|
||||
|
||||
def resources: ResourceProvider
|
||||
|
||||
@@ -39,6 +44,23 @@ abstract class BlockController[T <: TileController](val name: String, material:
|
||||
getTE(world, x, y, z).onClick(player)
|
||||
return true
|
||||
}
|
||||
|
||||
override def getTooltip(stack: ItemStack, player: EntityPlayer, advanced: Boolean): List[String] = {
|
||||
List(Misc.toLocal("bdlib.multiblock.tip.controller")) ++ (
|
||||
for ((kind, max) <- machine.modules) yield {
|
||||
val name = Misc.toLocalF(resources.getModuleName(kind))
|
||||
if (machine.required.getOrElse(kind, 0) > 0) {
|
||||
Misc.toLocalF("bdlib.multiblock.tip.module.range",
|
||||
EnumChatFormatting.YELLOW + name + EnumChatFormatting.RESET,
|
||||
EnumChatFormatting.YELLOW + machine.required(kind).toString + EnumChatFormatting.RESET,
|
||||
EnumChatFormatting.YELLOW + max.toString + EnumChatFormatting.RESET)
|
||||
} else {
|
||||
Misc.toLocalF("bdlib.multiblock.tip.module.max",
|
||||
EnumChatFormatting.YELLOW + name + EnumChatFormatting.RESET,
|
||||
EnumChatFormatting.YELLOW + max.toString + EnumChatFormatting.RESET)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
package net.bdew.lib.multiblock.block
|
||||
|
||||
import net.bdew.lib.block.{BlockRef, HasTE}
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.{BlockRef, BlockTooltip, HasTE}
|
||||
import net.bdew.lib.config.MachineManagerMultiblock
|
||||
import net.bdew.lib.multiblock.tile.TileModule
|
||||
import net.bdew.lib.multiblock.{ResourceProvider, Tools}
|
||||
import net.bdew.lib.render.connected.ConnectedTextureBlock
|
||||
@@ -18,11 +20,11 @@ import net.minecraft.block.material.Material
|
||||
import net.minecraft.entity.EntityLivingBase
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.ChatComponentTranslation
|
||||
import net.minecraft.util.{ChatComponentTranslation, EnumChatFormatting}
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
|
||||
abstract class BlockModule[T <: TileModule](val name: String, val kind: String, material: Material, val TEClass: Class[T])
|
||||
extends Block(material) with HasTE[T] with ConnectedTextureBlock {
|
||||
abstract class BlockModule[T <: TileModule](val name: String, val kind: String, material: Material, val TEClass: Class[T], val machines: MachineManagerMultiblock)
|
||||
extends Block(material) with HasTE[T] with ConnectedTextureBlock with BlockTooltip {
|
||||
|
||||
def resources: ResourceProvider
|
||||
|
||||
@@ -60,10 +62,27 @@ abstract class BlockModule[T <: TileModule](val name: String, val kind: String,
|
||||
p <- te.connected.value
|
||||
bl <- p.block(world)
|
||||
} yield {
|
||||
bl.onBlockActivated(world, p.x, p.y, p.z, player, meta, 0, 0, 0)
|
||||
}) getOrElse {
|
||||
bl.onBlockActivated(world, p.x, p.y, p.z, player, meta, 0, 0, 0)
|
||||
}) getOrElse {
|
||||
player.addChatMessage(new ChatComponentTranslation("bdlib.multiblock.notconnected"))
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
override def getTooltip(stack: ItemStack, player: EntityPlayer, advanced: Boolean): List[String] = {
|
||||
List(Misc.toLocal("bdlib.multiblock.tip.module")) ++ (
|
||||
for ((machine, (min, max)) <- machines.getMachinesForBlock(this)) yield {
|
||||
val name = machine.getController.getLocalizedName
|
||||
if (min > 0) {
|
||||
Misc.toLocalF("bdlib.multiblock.tip.module.range",
|
||||
EnumChatFormatting.YELLOW + name + EnumChatFormatting.RESET,
|
||||
EnumChatFormatting.YELLOW + min.toString + EnumChatFormatting.RESET,
|
||||
EnumChatFormatting.YELLOW + max.toString + EnumChatFormatting.RESET)
|
||||
} else {
|
||||
Misc.toLocalF("bdlib.multiblock.tip.module.max",
|
||||
EnumChatFormatting.YELLOW + name + EnumChatFormatting.RESET,
|
||||
EnumChatFormatting.YELLOW + max.toString + EnumChatFormatting.RESET)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ trait BlockOutput[T <: TileOutput[_]] extends BlockModule[T] with BlockAdditiona
|
||||
|
||||
def getFaceOverlays(world: IBlockAccess, x: Int, y: Int, z: Int, face: ForgeDirection): List[FaceOverlay] = {
|
||||
var result = List.empty[FaceOverlay]
|
||||
Option(getTE(world, x, y, z)) flatMap (_.getCore) map { core =>
|
||||
Option(getTE(world, x, y, z)) flatMap (_.getCore) foreach { core =>
|
||||
val bf = BlockFace(x, y, z, face)
|
||||
if (core.outputFaces.contains(bf))
|
||||
result :+= FaceOverlay(resources.output, resources.outputColors(core.outputFaces(bf)))
|
||||
|
||||
@@ -19,7 +19,7 @@ case class DataSlotPos(name: String, parent: DataSlotContainer) extends DataSlot
|
||||
setUpdate(UpdateKind.SAVE, UpdateKind.WORLD)
|
||||
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
value map (x => t.setTag(name, Misc.applyMutator(x.writeToNBT, new NBTTagCompound)))
|
||||
value foreach (x => t.setTag(name, Misc.applyMutator(x.writeToNBT, new NBTTagCompound)))
|
||||
}
|
||||
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
|
||||
@@ -14,11 +14,11 @@ import net.bdew.lib.gui.{Color, Point, Rect, Texture}
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
class WidgetInfo(val rect: Rect, icon: Texture, text: => String, tooltip: => String) extends Widget {
|
||||
class WidgetInfoMulti(val rect: Rect, icon: Texture, text: => String, tooltip: => List[String]) extends Widget {
|
||||
final val iconRect = Rect(1, 1, 8, 8)
|
||||
|
||||
override def handleTooltip(p: Point, tip: mutable.MutableList[String]) {
|
||||
if (iconRect.contains(p) && tooltip != null) tip += tooltip
|
||||
if (iconRect.contains(p) && tooltip != null) tip ++= tooltip
|
||||
}
|
||||
|
||||
override def draw(mouse: Point) {
|
||||
@@ -26,3 +26,5 @@ class WidgetInfo(val rect: Rect, icon: Texture, text: => String, tooltip: => Str
|
||||
parent.drawText(text, rect.origin +(12, 1), Color.darkGray, false)
|
||||
}
|
||||
}
|
||||
|
||||
class WidgetInfo(rect: Rect, icon: Texture, text: => String, tooltip: => String) extends WidgetInfoMulti(rect, icon, text, List(tooltip))
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
package net.bdew.lib.multiblock.gui
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.gui.widgets.Widget
|
||||
import net.bdew.lib.gui.{Point, Rect, Texture}
|
||||
@@ -24,7 +26,7 @@ class WidgetOutputIcon(p: Point, te: CIOutputFaces, output: Int) extends Widget
|
||||
val faces = te.outputFaces.inverted
|
||||
if (faces.isDefinedAt(output)) {
|
||||
val bf = faces(output)
|
||||
bf.origin.block(te.getWorldObj) map { block =>
|
||||
bf.origin.block(te.getWorldObj) foreach { block =>
|
||||
parent.drawTexture(rect, Texture(Texture.BLOCKS, block.getIcon(te.getWorldObj, bf.origin.x, bf.origin.y, bf.origin.z, bf.face.ordinal())))
|
||||
if (block.isInstanceOf[BlockAdditionalRender]) {
|
||||
for (over <- block.asInstanceOf[BlockAdditionalRender].getFaceOverlays(te.getWorldObj, bf.origin.x, bf.origin.y, bf.origin.z, bf.face))
|
||||
@@ -43,7 +45,7 @@ class WidgetOutputIcon(p: Point, te: CIOutputFaces, output: Int) extends Widget
|
||||
val bf = faces(output)
|
||||
bf.origin.block(te.getWorldObj) map { block =>
|
||||
tip += block.getLocalizedName
|
||||
tip += "%d, %d, %d - %s".format(bf.x, bf.y, bf.z, Misc.toLocal("bdlib.multiblock.face." + bf.face.toString.toLowerCase))
|
||||
tip += "%d, %d, %d - %s".format(bf.x, bf.y, bf.z, Misc.toLocal("bdlib.multiblock.face." + bf.face.toString.toLowerCase(Locale.US)))
|
||||
}
|
||||
} else {
|
||||
tip += Misc.toLocal("bdlib.multiblock.disabled")
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
package net.bdew.lib.multiblock.gui
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.gui.widgets.{WidgetButtonIcon, WidgetSubContainer}
|
||||
import net.bdew.lib.gui.{Point, Rect}
|
||||
@@ -37,7 +39,7 @@ class WidgetRSConfig(te: CIOutputFaces, output: Int, p: Point) extends WidgetSub
|
||||
|
||||
override def draw(mouse: Point) {
|
||||
bt.icon = icons(cfg.rsMode)
|
||||
bt.hover = Misc.toLocal("bdlib.rsmode." + cfg.rsMode.toString.toLowerCase)
|
||||
bt.hover = Misc.toLocal("bdlib.rsmode." + cfg.rsMode.toString.toLowerCase(Locale.US))
|
||||
super.draw(mouse)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import net.bdew.lib.multiblock.{MachineCore, ResourceProvider, Tools}
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
|
||||
trait TileController extends TileDataSlots {
|
||||
val modules = new DataSlotPosSet("modules", this).setUpdate(UpdateKind.WORLD, UpdateKind.SAVE, UpdateKind.RENDER)
|
||||
val modules = new DataSlotPosSet("modules", this).setUpdate(UpdateKind.WORLD, UpdateKind.SAVE)
|
||||
|
||||
def resources: ResourceProvider
|
||||
def cfg: MachineCore
|
||||
@@ -29,7 +29,7 @@ trait TileController extends TileDataSlots {
|
||||
|
||||
lazy val myPos = BlockRef(xCoord, yCoord, zCoord)
|
||||
|
||||
def getNumOfModules(kind: String) = modules.map(_.getTile[TileModule](getWorldObj)).flatten.count(_.kind == kind)
|
||||
def getNumOfModules(kind: String) = modules.flatMap(_.getTile[TileModule](getWorldObj)).count(_.kind == kind)
|
||||
|
||||
def onModulesChanged()
|
||||
def onClick(player: EntityPlayer)
|
||||
@@ -59,7 +59,7 @@ trait TileController extends TileDataSlots {
|
||||
|
||||
def validateModules() {
|
||||
modules.filter(x => {
|
||||
!x.getTile[TileModule](getWorldObj).isDefined || !x.getBlock[BlockModule[TileModule]](getWorldObj).isDefined
|
||||
x.getTile[TileModule](getWorldObj).isEmpty || x.getBlock[BlockModule[TileModule]](getWorldObj).isEmpty
|
||||
}).foreach(x => {
|
||||
BdLib.logWarn("Block at %s is not a valid module, removing from machine %s at %d,%d,%d", x, this.getClass.getSimpleName, xCoord, yCoord, zCoord)
|
||||
modules.remove(x)
|
||||
|
||||
@@ -10,21 +10,17 @@
|
||||
package net.bdew.lib.multiblock.tile
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.util.{ChatComponentTranslation, ChatStyle, EnumChatFormatting}
|
||||
|
||||
abstract class TileControllerGui extends TileController {
|
||||
def openGui(player: EntityPlayer)
|
||||
|
||||
def onClick(player: EntityPlayer) = {
|
||||
import net.bdew.lib.helpers.ChatHelper._
|
||||
val missing = cfg.required.filter({ case (mod, cnt) => getNumOfModules(mod) < cnt })
|
||||
if (missing.size > 0) {
|
||||
player.addChatMessage(new ChatComponentTranslation("bdlib.multiblock.incomplete")
|
||||
.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED)))
|
||||
if (missing.nonEmpty) {
|
||||
player.addChatMessage(L("bdlib.multiblock.incomplete").setColor(Color.RED))
|
||||
for ((mod, cnt) <- missing)
|
||||
player.addChatMessage(
|
||||
new ChatComponentTranslation("- %s %s", Integer.valueOf(cnt),
|
||||
new ChatComponentTranslation(resources.getModuleName(mod)))
|
||||
.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED)))
|
||||
player.addChatMessage(L("- %s %s", cnt.toString, L(resources.getModuleName(mod))).setColor(Color.RED))
|
||||
} else openGui(player)
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ abstract class TileOutput[T <: OutputConfig] extends TileModule with MIOutput[T]
|
||||
def onConnectionsChanged(added: Set[ForgeDirection], removed: Set[ForgeDirection]) {}
|
||||
|
||||
def doRescanFaces() {
|
||||
getCore map { core =>
|
||||
getCore foreach { core =>
|
||||
val connections = (
|
||||
ForgeDirection.VALID_DIRECTIONS
|
||||
filterNot { dir => core.modules.contains(myPos.neighbour(dir)) }
|
||||
@@ -58,7 +58,7 @@ abstract class TileOutput[T <: OutputConfig] extends TileModule with MIOutput[T]
|
||||
val toRemove = known -- connections
|
||||
toRemove.foreach(x => core.removeOutput(myPos, x))
|
||||
toAdd.foreach(x => core.newOutput(myPos, x, makeCfgObject(x)))
|
||||
if (toAdd.size > 0 || toRemove.size > 0) {
|
||||
if (toAdd.nonEmpty || toRemove.nonEmpty) {
|
||||
onConnectionsChanged(toAdd, toRemove)
|
||||
getWorldObj.markBlockForUpdate(xCoord, yCoord, zCoord)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.nbt
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.{NBTBase, NBTTagByte, NBTTagCompound, NBTTagList}
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
object NBT {
|
||||
|
||||
class NBTSerialized(val value: NBTBase) extends AnyVal
|
||||
|
||||
object NBTSerialized {
|
||||
implicit def serializeNbtPrimitive[T: Type](v: T): NBTSerialized = new NBTSerialized(Type[T].toNBT(v))
|
||||
|
||||
implicit def serializeNbtList[T: Type](v: Traversable[T]): NBTSerialized = {
|
||||
val list = new NBTTagList
|
||||
for (x <- v) list.appendTag(Type[T].toNBT(x))
|
||||
new NBTSerialized(list)
|
||||
}
|
||||
|
||||
// Boolean is special because it's represented as a byte in NBT
|
||||
implicit def serializeBoolean(v: Boolean): NBTSerialized = new NBTSerialized(new NBTTagByte(if (v) 1 else 0))
|
||||
|
||||
// Itemstack serialization helpers
|
||||
implicit def serializeItemStack(v: ItemStack): NBTSerialized = new NBTSerialized(NBT.from(v.writeToNBT _))
|
||||
implicit def serializeItemStackList(v: Traversable[ItemStack]): NBTSerialized = serializeNbtList(v map (x => NBT.from(x.writeToNBT _)))
|
||||
}
|
||||
|
||||
def apply(pairs: (String, NBTSerialized)*): NBTTagCompound = {
|
||||
val tag = new NBTTagCompound()
|
||||
for ((k, v) <- pairs)
|
||||
tag.setTag(k, v.value)
|
||||
tag
|
||||
}
|
||||
|
||||
def from(f: (NBTTagCompound) => _) = {
|
||||
val v = new NBTTagCompound
|
||||
f(v)
|
||||
v
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
package net.bdew.lib.nbt
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.{NBTTagCompound, NBTTagList}
|
||||
|
||||
import scala.language.implicitConversions
|
||||
@@ -27,4 +28,5 @@ class RichNBTTagCompound(tag: NBTTagCompound) {
|
||||
tag.setTag(name, list)
|
||||
}
|
||||
|
||||
def toItemStack = Option(ItemStack.loadItemStackFromNBT(tag))
|
||||
}
|
||||
@@ -34,6 +34,7 @@ case class DataSlotPower(name: String, parent: DataSlotContainer) extends DataSl
|
||||
val canExtract = Misc.clamp(v, 0F, stored)
|
||||
if ((canExtract > 0) && !simulate) {
|
||||
stored -= canExtract
|
||||
if (stored < 1) stored = 0
|
||||
parent.dataSlotChanged(this)
|
||||
}
|
||||
return canExtract
|
||||
|
||||
@@ -13,12 +13,11 @@ import net.bdew.lib.data.DataSlotFloat
|
||||
import net.bdew.lib.data.base.{TileDataSlots, UpdateKind}
|
||||
import net.bdew.lib.machine.ProcessorMachine
|
||||
import net.bdew.lib.tile.TileExtended
|
||||
import net.bdew.lib.tile.inventory.{BreakableInventoryTile, PersistentInventoryTile, SidedInventory}
|
||||
import net.bdew.lib.tile.inventory.{PersistentInventoryTile, SidedInventory}
|
||||
|
||||
abstract class TileBaseProcessor extends TileExtended
|
||||
with TileDataSlots
|
||||
with PersistentInventoryTile
|
||||
with BreakableInventoryTile
|
||||
with SidedInventory
|
||||
with TilePoweredBase {
|
||||
def cfg: ProcessorMachine
|
||||
|
||||
@@ -12,7 +12,7 @@ package net.bdew.lib.recipes
|
||||
import java.io._
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler
|
||||
import net.bdew.lib.BdLib
|
||||
import net.bdew.lib.{BdLib, Misc}
|
||||
|
||||
object RecipesHelper {
|
||||
/**
|
||||
@@ -26,15 +26,14 @@ object RecipesHelper {
|
||||
def loadConfigs(modName: String, listResource: String, configDir: File, resBaseName: String, loader: RecipeLoader) {
|
||||
BdLib.logInfo("Loading internal config files for mod %s", modName)
|
||||
|
||||
val listReader = new BufferedReader(new InputStreamReader(getClass.getResourceAsStream(listResource)))
|
||||
val internals = Iterator.continually(listReader.readLine)
|
||||
.takeWhile(_ != null)
|
||||
.map(_.trim)
|
||||
.filterNot(_.startsWith("#"))
|
||||
.filterNot(_.isEmpty)
|
||||
.toList
|
||||
listReader.close()
|
||||
|
||||
val internals = Misc.withAutoClose(new BufferedReader(new InputStreamReader(getClass.getResourceAsStream(listResource)))) { listReader =>
|
||||
Iterator.continually(listReader.readLine)
|
||||
.takeWhile(_ != null)
|
||||
.map(_.trim)
|
||||
.filterNot(_.startsWith("#"))
|
||||
.filterNot(_.isEmpty)
|
||||
.toList
|
||||
}
|
||||
|
||||
val overrideDir = new File(configDir, "overrides")
|
||||
if (!overrideDir.exists()) overrideDir.mkdir()
|
||||
@@ -44,9 +43,10 @@ object RecipesHelper {
|
||||
if (overrideFile.exists()) {
|
||||
tryLoadConfig(new FileReader(overrideFile), overrideFile.getCanonicalPath, modName, loader)
|
||||
} else {
|
||||
val resource = resBaseName + fileName
|
||||
tryLoadConfig(new InputStreamReader(getClass.getResourceAsStream(resource)),
|
||||
getClass.getResource(resource).toString, modName, loader)
|
||||
val url = getClass.getResource(resBaseName + fileName)
|
||||
Misc.withAutoClose(url.openStream()) { stream =>
|
||||
tryLoadConfig(new InputStreamReader(stream), url.toString, modName, loader)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
package net.bdew.lib.recipes.gencfg
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
import net.bdew.lib.gui.Color
|
||||
|
||||
abstract class ConfigEntry
|
||||
@@ -43,7 +45,7 @@ case class ConfigSection(pfx: String = "") extends ConfigEntry with Iterable[(St
|
||||
def getSection(id: String) = getRaw(id, classOf[ConfigSection])
|
||||
|
||||
final val trueVals = Set("y", "true", "yes", "on")
|
||||
def getBoolean(id: String) = trueVals.contains(getString(id).toLowerCase)
|
||||
def getBoolean(id: String) = trueVals.contains(getString(id).toLowerCase(Locale.US))
|
||||
|
||||
def hasValue(id: String) = raw.isDefinedAt(id)
|
||||
|
||||
@@ -59,8 +61,8 @@ case class ConfigSection(pfx: String = "") extends ConfigEntry with Iterable[(St
|
||||
|
||||
def getInt(id: String) = getDouble(id).round.toInt
|
||||
def getFloat(id: String) = getDouble(id).toFloat
|
||||
def getIntList(id: String) = getDoubleList(id).map(_.round.toInt).toList
|
||||
def getFloatList(id: String) = getDoubleList(id).map(_.toFloat).toList
|
||||
def getIntList(id: String) = getDoubleList(id).map(_.round.toInt)
|
||||
def getFloatList(id: String) = getDoubleList(id).map(_.toFloat)
|
||||
|
||||
def getColor(id: String) =
|
||||
raw(id) match {
|
||||
|
||||
@@ -14,10 +14,10 @@ import net.bdew.lib.recipes.gencfg.ConfigEntry
|
||||
|
||||
/**
|
||||
* Allows definition of random-weighted loot/drop lists in config sections
|
||||
* @param list List on (chance percent, stack reference) pairs, resolve to
|
||||
* @param list List of (chance percent, stack reference) pairs, resolve to
|
||||
* real ItemStacks with LootListLoader.resolveLootList
|
||||
*/
|
||||
case class EntryLootList(list: List[(Int, StackRef)]) extends ConfigEntry
|
||||
case class EntryLootList(list: List[(Double, StackRef)]) extends ConfigEntry
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ import net.minecraftforge.oredict.OreDictionary
|
||||
* Loader mixin for loot lists
|
||||
*/
|
||||
trait LootListLoader extends GenericConfigLoader {
|
||||
def resolveLootList(entry: EntryLootList): List[(Int, ItemStack)] = resolveLootList(entry.list)
|
||||
def resolveLootList(list: List[(Int, StackRef)]) =
|
||||
def resolveLootList(entry: EntryLootList): List[(Double, ItemStack)] = resolveLootList(entry.list)
|
||||
def resolveLootList(list: List[(Double, StackRef)]) =
|
||||
(for ((chance, ref) <- list) yield {
|
||||
try {
|
||||
val itemStack = getConcreteStack(ref)
|
||||
|
||||
@@ -19,7 +19,7 @@ import net.bdew.lib.recipes.gencfg.GenericConfigParser
|
||||
* )
|
||||
*/
|
||||
trait LootListParser extends GenericConfigParser {
|
||||
def dropsEntry = (wholeNumber <~ "%") ~ spec ^^ { case n ~ s => (n.toInt, s) }
|
||||
def dropsEntry = (decimalNumber <~ "%") ~ spec ^^ { case n ~ s => (n.toDouble, s) }
|
||||
def ceDrops = "DropsList" ~> "(" ~> dropsEntry.* <~ ")" ^^ EntryLootList
|
||||
override def cfgValue = ceDrops | super.cfgValue
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import net.minecraftforge.common.MinecraftForge
|
||||
class IconPreloader(kind: Int) {
|
||||
lazy val map = {
|
||||
(for {
|
||||
method <- getClass.getMethods if method.getParameterTypes.length == 0 && classOf[TextureLoc].isAssignableFrom(method.getReturnType)
|
||||
method <- getClass.getMethods if method.getParameterTypes.isEmpty && classOf[TextureLoc].isAssignableFrom(method.getReturnType)
|
||||
value <- Misc.asInstanceOpt(method.invoke(this), classOf[TextureLoc])
|
||||
} yield method.getName -> value).toMap
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ case class DataSlotResourceKindOption(name: String, parent: DataSlotContainer) e
|
||||
setUpdate(UpdateKind.SAVE, UpdateKind.GUI)
|
||||
|
||||
override def save(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
value map { r =>
|
||||
value foreach { r =>
|
||||
t.setTag(name,
|
||||
Misc.applyMutator(new NBTTagCompound) { tag =>
|
||||
r.helperObject.saveToNBT(tag, r)
|
||||
|
||||
@@ -13,5 +13,5 @@ import net.bdew.lib.data.DataSlotDirection
|
||||
import net.bdew.lib.data.base.{TileDataSlots, UpdateKind}
|
||||
|
||||
trait RotatableTile extends TileDataSlots {
|
||||
var rotation = DataSlotDirection("rotation", this).setUpdate(UpdateKind.SAVE, UpdateKind.WORLD)
|
||||
var rotation = DataSlotDirection("rotation", this).setUpdate(UpdateKind.SAVE, UpdateKind.WORLD, UpdateKind.RENDER)
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import net.minecraft.inventory.{IInventory, Slot}
|
||||
|
||||
class SlotSensorType[T, R](inv: IInventory, index: Int, x: Int, y: Int, ds: DataSlotSensor[T, R], types: => Seq[GenericSensorType[T, R]]) extends Slot(inv, index, x, y) with SlotClickable {
|
||||
override def onClick(button: Int, mods: Int, player: EntityPlayer) = {
|
||||
if (mods == 0 && (button == 0 || button == 1) && types.size > 0 && player.inventory.getItemStack == null) {
|
||||
if (mods == 0 && (button == 0 || button == 1) && types.nonEmpty && player.inventory.getItemStack == null) {
|
||||
val newSensor =
|
||||
if (button == 0)
|
||||
Misc.nextInSeq(types, ds.sensor)
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
package net.bdew.lib.sensors.multiblock
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.gui._
|
||||
@@ -58,7 +60,7 @@ trait SensorOutput extends GenericSensorType[TileEntity, Boolean] {
|
||||
(current, obj) match {
|
||||
case (SensorOutputFlowParameter(n), x: CIOutputFaces) =>
|
||||
val outputs = x.outputFaces.map.values.toList.sorted
|
||||
if (outputs.size > 0)
|
||||
if (outputs.nonEmpty)
|
||||
if (button == 0)
|
||||
SensorOutputFlowParameter(Misc.nextInSeq(outputs, n))
|
||||
else
|
||||
@@ -102,7 +104,7 @@ trait SensorOutput extends GenericSensorType[TileEntity, Boolean] {
|
||||
val bf = faces(output)
|
||||
bf.origin.block(te.getWorldObj) foreach { block =>
|
||||
list :+= block.getLocalizedName
|
||||
list :+= "%d, %d, %d - %s".format(bf.x, bf.y, bf.z, Misc.toLocal("bdlib.multiblock.face." + bf.face.toString.toLowerCase))
|
||||
list :+= "%d, %d, %d - %s".format(bf.x, bf.y, bf.z, Misc.toLocal("bdlib.multiblock.face." + bf.face.toString.toLowerCase(Locale.US)))
|
||||
}
|
||||
}
|
||||
list
|
||||
|
||||
@@ -9,16 +9,15 @@
|
||||
|
||||
package net.bdew.lib.tile.inventory
|
||||
|
||||
import net.bdew.lib.block.HasTE
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.world.World
|
||||
|
||||
trait BreakableInventoryBlock extends Block {
|
||||
this: HasTE[_ <: BreakableInventoryTile] =>
|
||||
override def breakBlock(world: World, x: Int, y: Int, z: Int, block: Block, meta: Int) {
|
||||
if (!world.isRemote) {
|
||||
val te = world.getTileEntity(x, y, z).asInstanceOf[BreakableInventoryTile]
|
||||
if (te != null) {
|
||||
te.dropItems()
|
||||
}
|
||||
getTE(world, x, y, z).dropItems()
|
||||
}
|
||||
super.breakBlock(world, x, y, z, block, meta)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ trait BreakableInventoryTile extends TileEntity with BaseInventory {
|
||||
for (stack <- inv if stack != null) {
|
||||
ItemUtils.throwItemAt(getWorldObj, xCoord, yCoord, zCoord, stack)
|
||||
}
|
||||
inv = new Array[ItemStack](inv.size)
|
||||
inv = new Array[ItemStack](inv.length)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,11 +17,11 @@ import net.minecraft.tileentity.TileEntity
|
||||
trait InventoryProxy extends TileEntity with IInventory {
|
||||
def targetInventory: Option[IInventory]
|
||||
|
||||
override def openInventory() = targetInventory map (_.openInventory())
|
||||
override def closeInventory() = targetInventory map (_.closeInventory())
|
||||
override def openInventory() = targetInventory foreach (_.openInventory())
|
||||
override def closeInventory() = targetInventory foreach (_.closeInventory())
|
||||
|
||||
override def markDirty() = {
|
||||
targetInventory map (_.markDirty())
|
||||
targetInventory foreach (_.markDirty())
|
||||
super.markDirty()
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ trait InventoryProxy extends TileEntity with IInventory {
|
||||
|
||||
override def getStackInSlot(slot: Int) = targetInventory.map(_.getStackInSlot(slot)).orNull
|
||||
override def getStackInSlotOnClosing(slot: Int) = targetInventory.map(_.getStackInSlotOnClosing(slot)).orNull
|
||||
override def setInventorySlotContents(slot: Int, item: ItemStack) = targetInventory.map(_.setInventorySlotContents(slot, item))
|
||||
override def setInventorySlotContents(slot: Int, item: ItemStack) = targetInventory.foreach(_.setInventorySlotContents(slot, item))
|
||||
override def decrStackSize(slot: Int, num: Int) = targetInventory.map(_.decrStackSize(slot, num)).orNull
|
||||
|
||||
override def isItemValidForSlot(slot: Int, item: ItemStack) = targetInventory.exists(_.isItemValidForSlot(slot, item))
|
||||
|
||||
@@ -15,9 +15,9 @@ import net.minecraft.item.ItemStack
|
||||
|
||||
class MultipleInventoryAdapter(val map: Map[Int, (IInventory, Int)]) extends IInventory {
|
||||
def this(inventories: Iterable[IInventory]) =
|
||||
this((inventories map { inv => (0 until inv.getSizeInventory).map((inv, _)) }).flatten.zipWithIndex.map(_.swap).toMap)
|
||||
this((inventories flatMap { inv => (0 until inv.getSizeInventory).map((inv, _)) }).zipWithIndex.map(_.swap).toMap)
|
||||
def this(inventories: IInventory*) =
|
||||
this((inventories map { inv => (0 until inv.getSizeInventory).map((inv, _)) }).flatten.zipWithIndex.map(_.swap).toMap)
|
||||
this((inventories flatMap { inv => (0 until inv.getSizeInventory).map((inv, _)) }).zipWithIndex.map(_.swap).toMap)
|
||||
|
||||
lazy val inventories = map.values.map(_._1).toSet
|
||||
override lazy val getInventoryStackLimit = inventories.map(_.getInventoryStackLimit).min
|
||||
|
||||
@@ -15,7 +15,7 @@ import net.minecraft.item.ItemStack
|
||||
trait SidedInventory extends BaseInventory with ISidedInventory {
|
||||
var allowSided = false
|
||||
|
||||
def getAccessibleSlotsFromSide(side: Int): Array[Int] = (0 until inv.size).toArray
|
||||
def getAccessibleSlotsFromSide(side: Int): Array[Int] = inv.indices.toArray
|
||||
|
||||
def canInsertItem(slot: Int, stack: ItemStack, side: Int) = allowSided && isItemValidForSlot(slot, stack)
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tooltip
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraftforge.fluids.{FluidContainerRegistry, FluidStack, IFluidContainerItem}
|
||||
|
||||
trait FluidTooltipProvider extends TooltipProvider {
|
||||
def getFluid(is: ItemStack): Option[FluidStack] = {
|
||||
if (is.getItem.isInstanceOf[IFluidContainerItem]) {
|
||||
Option(is.getItem.asInstanceOf[IFluidContainerItem].getFluid(is))
|
||||
} else {
|
||||
Option(FluidContainerRegistry.getFluidForFilledItem(is))
|
||||
}
|
||||
}
|
||||
|
||||
override def shouldHandleTooltip(stack: ItemStack): Boolean = getFluid(stack) exists shouldHandleTooltip
|
||||
override def handleTooltip(stack: ItemStack, advanced: Boolean, shift: Boolean): Iterable[String] =
|
||||
getFluid(stack) map (f => handleTooltip(f, advanced, shift)) getOrElse Iterable.empty
|
||||
|
||||
def shouldHandleTooltip(fluid: FluidStack): Boolean
|
||||
def handleTooltip(fluid: FluidStack, advanced: Boolean, shift: Boolean): Iterable[String]
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tooltip
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent
|
||||
import net.bdew.lib.{BdLib, Client}
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.event.entity.player.ItemTooltipEvent
|
||||
|
||||
object TooltipHandler {
|
||||
var registry = List.empty[TooltipProvider]
|
||||
|
||||
def init() {
|
||||
MinecraftForge.EVENT_BUS.register(this)
|
||||
}
|
||||
|
||||
def register(p: TooltipProvider) = registry :+= p
|
||||
|
||||
@SubscribeEvent
|
||||
def handleTooltipEvent(ev: ItemTooltipEvent): Unit = {
|
||||
if (ev.itemStack == null || ev.itemStack.getItem == null) return
|
||||
|
||||
val toAdd = for (provider <- registry) yield {
|
||||
try {
|
||||
if (provider.shouldHandleTooltip(ev.itemStack))
|
||||
Some(provider.handleTooltip(ev.itemStack, ev.showAdvancedItemTooltips, Client.shiftDown))
|
||||
else
|
||||
None
|
||||
} catch {
|
||||
case t: Throwable =>
|
||||
BdLib.logErrorException("Error in tooltip provider %s", t, provider)
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
ev.toolTip ++= toAdd.flatten.flatten
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2015
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://bdew.net/minecraft-mod-public-license/
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tooltip
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
trait TooltipProvider {
|
||||
def shouldHandleTooltip(stack: ItemStack): Boolean
|
||||
def handleTooltip(stack: ItemStack, advanced: Boolean, shift: Boolean): Iterable[String]
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user