-
Notifications
You must be signed in to change notification settings - Fork 183
/
MinecraftFacetDetector.kt
146 lines (125 loc) · 5.52 KB
/
MinecraftFacetDetector.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
* Minecraft Dev for IntelliJ
*
* https://minecraftdev.org
*
* Copyright (c) 2021 minecraft-dev
*
* MIT License
*/
package com.demonwav.mcdev.facet
import com.demonwav.mcdev.platform.PlatformType
import com.demonwav.mcdev.platform.sponge.framework.SPONGE_LIBRARY_KIND
import com.demonwav.mcdev.util.ifEmpty
import com.demonwav.mcdev.util.runWriteTaskLater
import com.intellij.facet.FacetManager
import com.intellij.facet.impl.ui.libraries.LibrariesValidatorContextImpl
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ModuleRootEvent
import com.intellij.openapi.roots.ModuleRootListener
import com.intellij.openapi.roots.libraries.LibraryKind
import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager
import com.intellij.openapi.startup.StartupActivity
class MinecraftFacetDetector : StartupActivity {
override fun runActivity(project: Project) {
MinecraftModuleRootListener.doCheck(project)
}
private object MinecraftModuleRootListener : ModuleRootListener {
override fun rootsChanged(event: ModuleRootEvent) {
if (event.isCausedByFileTypesChange) {
return
}
val project = event.source as? Project ?: return
doCheck(project)
}
fun doCheck(project: Project) {
val moduleManager = ModuleManager.getInstance(project)
for (module in moduleManager.modules) {
val facetManager = FacetManager.getInstance(module)
val minecraftFacet = facetManager.getFacetByType(MinecraftFacet.ID)
if (minecraftFacet == null) {
checkNoFacet(module)
} else {
checkExistingFacet(module, minecraftFacet)
}
}
}
private fun checkNoFacet(module: Module) {
val platforms = autoDetectTypes(module).ifEmpty { return }
val facetManager = FacetManager.getInstance(module)
val configuration = MinecraftFacetConfiguration()
configuration.state.autoDetectTypes.addAll(platforms)
val facetType = MinecraftFacet.facetTypeOrNull ?: return
val facet = facetManager.createFacet(facetType, "Minecraft", configuration, null)
runWriteTaskLater {
// Only add the new facet if there isn't a Minecraft facet already - double check here since this
// task may run much later
if (module.isDisposed || facet.isDisposed) {
// Module may be disposed before we run
return@runWriteTaskLater
}
if (facetManager.getFacetByType(MinecraftFacet.ID) == null) {
val model = facetManager.createModifiableModel()
model.addFacet(facet)
model.commit()
}
}
}
private fun checkExistingFacet(module: Module, facet: MinecraftFacet) {
val platforms = autoDetectTypes(module).ifEmpty { return }
val types = facet.configuration.state.autoDetectTypes
types.clear()
types.addAll(platforms)
if (facet.configuration.state.forgePatcher) {
// make sure Forge and MCP are present
types.add(PlatformType.FORGE)
types.add(PlatformType.MCP)
}
facet.refresh()
}
private fun autoDetectTypes(module: Module): Set<PlatformType> {
val presentationManager = LibraryPresentationManager.getInstance()
val context = LibrariesValidatorContextImpl(module)
val platformKinds = mutableSetOf<LibraryKind>()
context.rootModel
.orderEntries()
.using(context.modulesProvider)
.recursively()
.librariesOnly()
.forEachLibrary forEach@{ library ->
MINECRAFT_LIBRARY_KINDS.forEach { kind ->
if (presentationManager.isLibraryOfKind(library, context.librariesContainer, setOf(kind))) {
platformKinds.add(kind)
}
}
return@forEach true
}
context.rootModel
.orderEntries()
.using(context.modulesProvider)
.recursively()
.withoutLibraries()
.withoutSdk()
.forEachModule forEach@{ m ->
if (m.name.startsWith("SpongeAPI", ignoreCase = true)) {
// We don't want want to add parent modules in module groups
val moduleManager = ModuleManager.getInstance(m.project)
val groupPath = moduleManager.getModuleGroupPath(m)
if (groupPath == null) {
platformKinds.add(SPONGE_LIBRARY_KIND)
return@forEach true
}
val name = groupPath.lastOrNull() ?: return@forEach true
if (m.name == name) {
return@forEach true
}
platformKinds.add(SPONGE_LIBRARY_KIND)
}
return@forEach true
}
return platformKinds.mapNotNull { kind -> PlatformType.fromLibraryKind(kind) }.toSet()
}
}
}