localized new version notification; added setting to turn off update checking; only showing new version notification in local games and to ops; cleaned up update check a little, storing result so we only need to query Github once (not on every player join), logging errors, using ComparableVersion for comparison

This commit is contained in:
Florian Nücke 2014-02-27 18:06:02 +01:00
parent 2fa6632ba9
commit 42126367d0
6 changed files with 63 additions and 52 deletions

View File

@ -175,6 +175,7 @@ class Settings(config: Config) {
OpenComputers.log.warning("Bad number of Remote Terminal counts, ignoring.")
Array(2, 4, 8)
}
val updateCheck = config.getBoolean("misc.updateCheck")
}

View File

@ -1,66 +1,68 @@
package li.cil.oc
import argo.jdom.{JsonNode, JsonRootNode, JdomParser}
import argo.jdom.JdomParser
import cpw.mods.fml.common.Loader
import cpw.mods.fml.common.versioning.ComparableVersion
import java.io.InputStreamReader
import java.net.{HttpURLConnection, URL}
import java.io.{InputStreamReader, BufferedReader}
import argo.saj.InvalidSyntaxException
import cpw.mods.fml.common.network.Player
import java.util.logging.Level
import net.minecraft.entity.player.EntityPlayerMP
import net.minecraft.util.ChatMessageComponent
import scala.collection.convert.WrapAsScala._
import cpw.mods.fml.common.versioning.{VersionParser, DefaultArtifactVersion}
class UpdateCheck(var version: String, player: EntityPlayerMP) extends Thread {
start()
object UpdateCheck {
val releasesUrl = new URL("https://api.github.com/repos/MightyPirates/OpenComputers/releases")
override def run() {
try {
val jsonString: String = getHTML("https://api.github.com/repos/MightyPirates/OpenComputers/releases")
val parser: JdomParser = new JdomParser
val n = parser.parse(jsonString)
val currentNumbers = version.split("\\.")
val mcVersion = currentNumbers(0)
val ocVersionCurrent = currentNumbers(1).toInt
val minorVersionCurrent = currentNumbers(2).toInt
val version = Loader.instance.getIndexedModList.get("OpenComputers").getVersion
val majorVersion = version.split('.')(0).toInt
n.getArrayNode().find(node => node.getStringValue("tag_name").split("v")(1).split("\\.")(0).equals(mcVersion) && !node.getBooleanValue("prerelease")) match {
case Some(node) =>
val version = node.getStringValue("tag_name")
val versions = version.split("v")(1).split("\\.")
val ocVersion = versions(1).toInt
val minorVersion = versions(2).toInt
if (ocVersionCurrent < ocVersion || (ocVersion == ocVersionCurrent && minorVersion > minorVersionCurrent)) {
player.sendChatToPlayer(ChatMessageComponent.createFromText("[OpenComputers] A new Version " + version + " is available!"))
// Lazy to make initialize() execute once from the first thread that tries to
// read it. If other threads are spawned while it's running they will wait,
// because lazy initializers are synchronized.
lazy val result = initialize()
def checkForPlayer(player: EntityPlayerMP) = if (Settings.get.updateCheck) {
new Thread() {
override def run() = result(player)
}.start()
}
case _ =>
def initialize(): EntityPlayerMP => Unit = {
try {
OpenComputers.log.info("Starting version check.")
releasesUrl.openConnection match {
case conn: HttpURLConnection =>
conn.setRequestMethod("GET")
conn.setDoOutput(false)
val json = new JdomParser().parse(new InputStreamReader(conn.getInputStream))
val candidates = json.getElements.filter(node => matchesVersion(node.getStringValue("tag_name")) && !node.getBooleanValue("prerelease"))
if (candidates.nonEmpty) {
val newest = candidates.maxBy(node => new ComparableVersion(node.getStringValue("tag_name").stripPrefix("v")))
val tag = newest.getStringValue("tag_name")
val tagVersion = new ComparableVersion(tag.stripPrefix("v"))
val modVersion = new ComparableVersion(version)
if (tagVersion.compareTo(modVersion) > 0) {
OpenComputers.log.info(s"A newer version is available: ($tag})")
return (player: EntityPlayerMP) =>
player.sendChatToPlayer(ChatMessageComponent.createFromText("§aOpenComputers§f: ").addFormatted(Settings.namespace + "gui.Chat.NewVersion", tag))
}
}
OpenComputers.log.info("Running the latest version.")
case _ => OpenComputers.log.warning("Failed to connect to Github.")
}
}
catch {
//Ignore not connected exceptions and stuff
case e: Exception =>
case t: Throwable => OpenComputers.log.log(Level.WARNING, "Update check failed.", t)
}
// Nothing to do, return dummy callback.
p =>
}
def getHTML(urlToRead: String): String = {
var url: URL = null
var conn: HttpURLConnection = null
var rd: BufferedReader = null
var line: String = null
val builder: StringBuilder = new StringBuilder
url = new URL(urlToRead)
conn = url.openConnection.asInstanceOf[HttpURLConnection]
conn.setRequestMethod("GET")
rd = new BufferedReader(new InputStreamReader(conn.getInputStream))
while ( {
line = rd.readLine
line
} != null) {
builder.append(line.trim).append("\n")
def matchesVersion(tag: String) = try {
tag.stripPrefix("v").split('.')(0).toInt == majorVersion
}
rd.close()
builder.toString()
catch {
case _: Throwable => false
}
}

View File

@ -1,16 +1,15 @@
package li.cil.oc.common
import cpw.mods.fml.common.{ModContainer, Loader}
import cpw.mods.fml.common.Loader
import cpw.mods.fml.common.network.{Player, IConnectionHandler}
import li.cil.oc.{UpdateCheck, Settings}
import li.cil.oc.util.LuaStateFactory
import li.cil.oc.util.mods.ProjectRed
import li.cil.oc.{UpdateCheck, Settings}
import net.minecraft.entity.player.EntityPlayerMP
import net.minecraft.network.packet.{Packet1Login, NetHandler}
import net.minecraft.network.{NetLoginHandler, INetworkManager}
import net.minecraft.server.MinecraftServer
import net.minecraft.util.ChatMessageComponent
import scala.collection.convert.WrapAsScala._
object ConnectionHandler extends IConnectionHandler {
def playerLoggedIn(player: Player, netHandler: NetHandler, manager: INetworkManager) {
@ -25,8 +24,10 @@ object ConnectionHandler extends IConnectionHandler {
if (!Settings.get.pureIgnorePower && !Loader.isModLoaded("UniversalElectricity")) {
p.sendChatToPlayer(ChatMessageComponent.createFromText("§aOpenComputers§f: ").addKey(Settings.namespace + "gui.Chat.WarningPower"))
}
val mod = Loader.instance.getIndexedModList.get("OpenComputers")
new UpdateCheck(mod.getVersion, p)
// Do update check in local games and for OPs.
if (!MinecraftServer.getServer.isDedicatedServer || MinecraftServer.getServer.getConfigurationManager.isPlayerOpped(p.getCommandSenderName)) {
UpdateCheck.checkForPlayer(p)
}
case _ =>
}
}

View File

@ -86,6 +86,7 @@ oc:gui.Analyzer.RobotXp=§6Erfahrung§f: %s (Stufe %s)
oc:gui.Analyzer.StoredEnergy=§6Gespeicherte Energie§f: %s
oc:gui.Analyzer.TotalEnergy=§6Insgesamt gespeicherte Energie§f: %s
oc:gui.Analyzer.Users=§6Benutzer§f: %s
oc:gui.Chat.NewVersion=Eine neue Version ist verfügbar: %s
oc:gui.Chat.WarningLuaFallback=Die native Lua-Implementierung ist nicht verfügbar. Computer können ihren Ausführungszustand nicht speichern. Sie werden automatisch neu starten, sobald ein Chunk neu geladen wird.
oc:gui.Chat.WarningPower=Universal Electricity 3 ist nicht verfügbar. Computer, Bildschirme und alle anderen Komponenten werden §lkeine§f Energie benötigen. UE3 wird auch benötigt, um zusätzlich BuildCraft, IndustrialCraft2 und Thermal Expansion zu unterstützen.
oc:gui.Chat.WarningProjectRed=Die verwendete Version von Project: Red ist nicht mit OpenComputers kompatibel. Aktualisiere bitte deine Version von Project: Red.

View File

@ -86,6 +86,7 @@ oc:gui.Analyzer.RobotXp=§6Experience§f: %s (Level %s)
oc:gui.Analyzer.StoredEnergy=§6Stored energy§f: %s
oc:gui.Analyzer.TotalEnergy=§6Total stored energy§f: %s
oc:gui.Analyzer.Users=§6Users§f: %s
oc:gui.Chat.NewVersion=A new version is available: %s
oc:gui.Chat.WarningLuaFallback=Native Lua libraries are not available, computers will not be able to persist their state. They will reboot on chunk reloads.
oc:gui.Chat.WarningPower=Universal Electricity 3 is not available. Computers, screens and all other components will §lnot§f require energy. Note that UE3 is also used to additionally support BuildCraft, IndustrialCraft2 and Thermal Expansion.
oc:gui.Chat.WarningProjectRed=You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red.

View File

@ -684,5 +684,10 @@ opencomputers {
# The number of remote terminals supported by each server tier.
terminalsPerTier: [2, 4, 8]
# Whether to perform an update check and informing local players and OPs
# if a new version is available (contacts Github once the first player
# joins a server / the first map in single player is opened).
updateCheck: true
}
}