Skip to content

Commit 641bc7b

Browse files
committed
Automatically download translations only when needed
1 parent e55960d commit 641bc7b

File tree

5 files changed

+105
-28
lines changed

5 files changed

+105
-28
lines changed

src/main/kotlin/xyz/bluspring/unitytranslate/commands/UnityTranslateCommands.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import xyz.bluspring.unitytranslate.UnityTranslate
88
import xyz.bluspring.unitytranslate.client.UnityTranslateClient
99
import xyz.bluspring.unitytranslate.client.transcribers.browser.BrowserSpeechTranscriber
1010
import xyz.bluspring.unitytranslate.translator.TranslatorManager
11-
import xyz.bluspring.unitytranslate.translator.UnityTranslateLibInstance
11+
import xyz.bluspring.unitytranslate.translator.library.UnityTranslateLibInstance
1212

1313
object UnityTranslateCommands {
1414
fun <S> register(dispatcher: CommandDispatcher<S>, root: String, isClient: Boolean, sender: (S, Component) -> Unit) {

src/main/kotlin/xyz/bluspring/unitytranslate/network/UTServerNetworking.kt

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package xyz.bluspring.unitytranslate.network
22

3+
import kotlinx.atomicfu.locks.synchronized
34
import kotlinx.coroutines.CompletableDeferred
45
import kotlinx.coroutines.CoroutineStart
56
import kotlinx.coroutines.launch
7+
import net.minecraft.ChatFormatting
8+
import net.minecraft.commands.Commands
9+
import net.minecraft.network.chat.Component
10+
import net.minecraft.server.level.ServerLevel
611
import net.minecraft.server.level.ServerPlayer
712
import net.minecraft.world.entity.player.Player
813
import xyz.bluspring.modernnetworking.api.minecraft.VanillaPacketSender
@@ -13,6 +18,8 @@ package xyz.bluspring.unitytranslate.network
1318
import xyz.bluspring.unitytranslate.network.payloads.SendTranscriptToClientPayload
1419
import xyz.bluspring.unitytranslate.network.payloads.ServerSupportPayload
1520
import xyz.bluspring.unitytranslate.translator.TranslatorManager
21+
import xyz.bluspring.unitytranslate.translator.library.TranslationModelDownloadQueue
22+
import xyz.bluspring.unitytranslate.translator.library.UnityTranslateLibInstance
1623
import java.util.*
1724
import java.util.concurrent.ConcurrentHashMap
1825
import java.util.concurrent.ConcurrentLinkedDeque
@@ -29,8 +36,9 @@ object UTServerNetworking {
2936

3037
registry.addServerboundHandler(PacketDefinitions.SET_USED_LANGUAGES) { packet, ctx ->
3138
val languages = EnumSet.copyOf(packet.languages)
32-
3339
usedLanguages[ctx.player.uuid] = languages
40+
41+
queueLanguagesToDownload()
3442
}
3543

3644
registry.addServerboundHandler(PacketDefinitions.SEND_TRANSCRIPT_TO_SERVER) { packet, ctx ->
@@ -87,11 +95,15 @@ object UTServerNetworking {
8795
registry.addServerboundHandler(PacketDefinitions.SET_CURRENT_LANGUAGE) { packet, ctx ->
8896
val language = packet.language
8997
playerLanguages[ctx.player.uuid] = language
98+
queueLanguagesToDownload()
9099
}
91100
}
92101

93102
fun onPlayerJoin(player: ServerPlayer) {
94-
VanillaPacketSender.sendToPlayer(player, ServerSupportPayload)
103+
if (UnityTranslateLibInstance.isLibraryLoaded)
104+
VanillaPacketSender.sendToPlayer(player, ServerSupportPayload)
105+
else if ((player.level() as ServerLevel).server.isSingleplayer || player.hasPermissions(Commands.LEVEL_ADMINS))
106+
player.displayClientMessage(Component.translatableWithFallback("unitytranslate.error.library_not_loaded", "[UnityTranslate] The UnityTranslate mod is installed on the server, but the translation library could not be loaded! This may be caused by using an unsupported platform, such as macOS, or using an ARM-based CPU architecture.\nIf you believe this to be in error, please report this as an issue with your server's system information!").withStyle(ChatFormatting.RED), false)
95107
}
96108

97109
fun onPlayerLeave(player: ServerPlayer) {
@@ -118,4 +130,16 @@ object UTServerNetworking {
118130
fun canPlayerRequestTranslations(player: Player): Boolean {
119131
return UnityTranslate.instance.proxy.hasTranscriptPermission(player)
120132
}
133+
134+
fun queueLanguagesToDownload() {
135+
synchronized(this.playerLanguages) {
136+
for (spoken in this.playerLanguages.values) {
137+
synchronized(this.usedLanguages) {
138+
for (translated in this.usedLanguages.values.flatten()) {
139+
TranslationModelDownloadQueue.queueDownload(spoken, translated)
140+
}
141+
}
142+
}
143+
}
144+
}
121145
}

src/main/kotlin/xyz/bluspring/unitytranslate/translator/TranslatorManager.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import xyz.bluspring.unitytranslate.compat.voicechat.UTVoiceChatCompat
1818
import xyz.bluspring.unitytranslate.library.util.collect
1919
import xyz.bluspring.unitytranslate.library.util.concurrent
2020
import xyz.bluspring.unitytranslate.network.payloads.MarkIncompletePayload
21+
import xyz.bluspring.unitytranslate.translator.library.UnityTranslateLibInstance
2122
import xyz.bluspring.unitytranslate.util.nativeaccess.CudaState
2223
import xyz.bluspring.unitytranslate.util.nativeaccess.NativeAccess
2324
import java.util.*
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package xyz.bluspring.unitytranslate.translator.library
2+
3+
import com.google.common.collect.Queues
4+
import kotlinx.coroutines.runBlocking
5+
import xyz.bluspring.unitytranslate.Language
6+
import xyz.bluspring.unitytranslate.UnityTranslate
7+
import xyz.bluspring.unitytranslate.library.UnityTranslateLib
8+
import java.util.*
9+
10+
object TranslationModelDownloadQueue {
11+
val library: UnityTranslateLib?
12+
get() {
13+
return if (UnityTranslateLibInstance.isLibraryLoaded)
14+
UnityTranslateLibInstance.library
15+
else null
16+
}
17+
18+
private val alreadyDownloaded = Collections.synchronizedSet(mutableSetOf<Pair<Language, Language>>())
19+
20+
private val queue = Queues.newSynchronousQueue<Pair<Language, Language>>()
21+
@Volatile
22+
private var downloadThread: DownloadThread? = null
23+
24+
fun queueDownload(from: Language, to: Language) {
25+
if (library == null) {
26+
throw IllegalStateException("UnityTranslateLib was not initialized!")
27+
}
28+
29+
val langPair = from to to
30+
31+
if (this.alreadyDownloaded.contains(langPair))
32+
return
33+
34+
if (this.queue.contains(langPair))
35+
return
36+
37+
this.queue.add(langPair)
38+
this.tryStartDownloadThread()
39+
}
40+
41+
private fun tryStartDownloadThread() {
42+
if (this.downloadThread == null) {
43+
this.downloadThread = DownloadThread()
44+
this.downloadThread!!.start()
45+
}
46+
}
47+
48+
private class DownloadThread : Thread("UnityTranslate Translation Model Download Thread") {
49+
override fun run() {
50+
while (queue.isNotEmpty()) {
51+
val langPair = queue.poll() ?: break
52+
val (from, to) = langPair
53+
val library = library!!
54+
55+
runBlocking {
56+
for (index in library.packageIndex.indexList) {
57+
try {
58+
val infos = index.getOrDownloadModelInfos(from.code, to.code)
59+
UnityTranslate.logger.info("Successfully downloaded translation models ${infos.keys.joinToString(", ") { "${it.fromCode} -> ${it.toCode}" }} from package index ${index.name}")
60+
} catch (e: Throwable) {
61+
UnityTranslate.logger.error("Failed to download translation models from package index ${index.name} for languages ${from.code} -> ${to.code}", e)
62+
}
63+
}
64+
}
65+
66+
alreadyDownloaded.add(langPair)
67+
}
68+
69+
downloadThread = null
70+
}
71+
}
72+
}

src/main/kotlin/xyz/bluspring/unitytranslate/translator/UnityTranslateLibInstance.kt renamed to src/main/kotlin/xyz/bluspring/unitytranslate/translator/library/UnityTranslateLibInstance.kt

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
package xyz.bluspring.unitytranslate.translator
1+
package xyz.bluspring.unitytranslate.translator.library
22

33
import com.google.common.collect.HashMultimap
44
import com.google.common.collect.Multimap
5-
import kotlinx.coroutines.Dispatchers
6-
import kotlinx.coroutines.flow.asFlow
7-
import kotlinx.coroutines.runBlocking
8-
import net.fabricmc.loader.api.FabricLoader
95
import xyz.bluspring.unitytranslate.Language
106
import xyz.bluspring.unitytranslate.UnityTranslate
117
import xyz.bluspring.unitytranslate.library.UnityTranslateLib
8+
import xyz.bluspring.unitytranslate.translator.LibreTranslateInstance
9+
import xyz.bluspring.unitytranslate.translator.TranslatorManager
1210

1311
class UnityTranslateLibInstance private constructor(): LibreTranslateInstance("", 150) {
1412
override val supportedLanguages: Multimap<Language, Language>
@@ -55,29 +53,11 @@ class UnityTranslateLibInstance private constructor(): LibreTranslateInstance(""
5553
try {
5654
library.load()
5755

58-
if (FabricLoader.getInstance().isDevelopmentEnvironment) {
59-
runBlocking(Dispatchers.IO) {
60-
for (index in library.packageIndex.indexList) {
61-
index.packages.chunked(10).asFlow().collect {
62-
// only download what's necessary for now
63-
UnityTranslate.logger.info("Downloading translation model for en -> es")
64-
index.getOrDownloadModelInfos("en", "es")
65-
66-
UnityTranslate.logger.info("Downloading translation model for es -> en")
67-
index.getOrDownloadModelInfos("es", "en")
68-
69-
UnityTranslate.logger.info("Downloaded all testing translation models!")
70-
}
71-
}
72-
}
73-
}
74-
7556
instance = UnityTranslateLibInstance()
7657
isLibraryLoaded = true
7758
} catch (e: Throwable) {
78-
UnityTranslate.logger.error("Failed to load UnityTranslateLib!")
79-
e.printStackTrace()
59+
UnityTranslate.logger.error("Failed to load UnityTranslateLib!", e)
8060
}
8161
}
8262
}
83-
}
63+
}

0 commit comments

Comments
 (0)