|
| 1 | +package generations.gg.generations.core.generationscore.common |
| 2 | + |
| 3 | +import com.cobblemon.mod.common.api.Priority |
| 4 | +import com.cobblemon.mod.common.api.data.DataProvider |
| 5 | +import com.cobblemon.mod.common.api.data.DataRegistry |
| 6 | +import com.cobblemon.mod.common.api.reactive.SimpleObservable.subscribe |
| 7 | +import com.cobblemon.mod.common.platform.events.PlatformEvents |
| 8 | +import com.cobblemon.mod.common.platform.events.ServerPlayerEvent.Logout.player |
| 9 | +import com.cobblemon.mod.common.util.ifClient |
| 10 | +import com.cobblemon.mod.common.util.server |
| 11 | +import dev.architectury.platform.Platform |
| 12 | +import dev.architectury.utils.Env |
| 13 | +import dev.architectury.utils.EnvExecutor |
| 14 | +import generations.gg.generations.core.generationscore.common.client.CompiledModelLoader |
| 15 | +import generations.gg.generations.core.generationscore.common.network.packets.S2CUnlockReloadPacket |
| 16 | +import generations.gg.generations.core.generationscore.common.world.shop.ShopPresets |
| 17 | +import generations.gg.generations.core.generationscore.common.world.shop.Shops |
| 18 | +import net.minecraft.resources.ResourceLocation |
| 19 | +import net.minecraft.server.level.ServerPlayer |
| 20 | +import net.minecraft.server.packs.PackType |
| 21 | +import net.minecraft.server.packs.resources.ResourceManager |
| 22 | +import net.minecraft.server.packs.resources.ResourceManagerReloadListener |
| 23 | +import java.util.* |
| 24 | +import java.util.function.Consumer |
| 25 | +import kotlin.jvm.functions.Function0 |
| 26 | +import kotlin.jvm.functions.Function0.invoke |
| 27 | + |
| 28 | +class GenerationsDataProvider : DataProvider { |
| 29 | + // Both Forge n Fabric keep insertion order so if a registry depends on another simply register it after |
| 30 | + internal var canReload = true |
| 31 | + // Both Forge n Fabric keep insertion order so if a registry depends on another simply register it after |
| 32 | + private val registries = linkedSetOf<DataRegistry>() |
| 33 | + private val synchronizedPlayerIds = mutableListOf<UUID>() |
| 34 | + |
| 35 | + private val scheduledActions = mutableMapOf<UUID, MutableList<() -> Unit>>() |
| 36 | + |
| 37 | + fun registerDefaults() { |
| 38 | + this.register(Shops) |
| 39 | + this.register(ShopPresets) |
| 40 | + PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe(Priority.HIGH) { |
| 41 | + synchronizedPlayerIds.remove(it.player.uuid) |
| 42 | + S2CUnlockReloadPacket().sendToPlayer(it.player) |
| 43 | + } |
| 44 | + |
| 45 | + ifClient { |
| 46 | + GenerationsCore.implementation.registerResourceReloader(GenerationsCore.id("client_resources"), SimpleResourceReloader(PackType.CLIENT_RESOURCES), PackType.CLIENT_RESOURCES, emptyList()) |
| 47 | + GenerationsCore.implementation.registerResourceReloader(GenerationsCore.id("model_registry"), CompiledModelLoader(), PackType.CLIENT_RESOURCES, emptyList()) |
| 48 | + } |
| 49 | + |
| 50 | + GenerationsCore.implementation.registerResourceReloader(GenerationsCore.id("data_resources"), SimpleResourceReloader(PackType.SERVER_DATA), PackType.SERVER_DATA, emptyList()) |
| 51 | + } |
| 52 | + |
| 53 | + override fun doAfterSync(player: ServerPlayer, action: () -> Unit) { |
| 54 | + if (synchronizedPlayerIds.contains(player.uuid)) { |
| 55 | + action.invoke() |
| 56 | + } else { |
| 57 | + scheduledActions.computeIfAbsent(player.uuid) { mutableListOf() }.add(action) |
| 58 | + } |
| 59 | + } |
| 60 | + |
| 61 | + override fun <T : DataRegistry> register(registry: T): T { |
| 62 | + registries.add(registry) |
| 63 | + GenerationsCore.LOGGER.info("Registered the {} registry", registry.id) |
| 64 | + GenerationsCore.LOGGER.debug("Registered the {} registry of class {}", registry.id, registry.javaClass.canonicalName) |
| 65 | + return registry |
| 66 | + } |
| 67 | + |
| 68 | + override fun fromIdentifier(registryIdentifier: ResourceLocation): DataRegistry? { |
| 69 | + return registries.stream().filter { it: DataRegistry? -> it!!.id == registryIdentifier }.findAny().orElse(null) |
| 70 | + } |
| 71 | + |
| 72 | + override fun sync(player: ServerPlayer) { |
| 73 | + if (!player.connection.connection.isMemoryConnection) { |
| 74 | + registries.forEach(Consumer { registry: DataRegistry? -> registry!!.sync(player) }) |
| 75 | + } |
| 76 | + |
| 77 | + // CobblemonEvents.DATA_SYNCHRONIZED.emit(player) |
| 78 | + val waitingActions = scheduledActions.remove(player.uuid) ?: return |
| 79 | + waitingActions.forEach { it() } |
| 80 | + } |
| 81 | + |
| 82 | + |
| 83 | + internal inner class SimpleResourceReloader(private val type: PackType) : ResourceManagerReloadListener { |
| 84 | + override fun onResourceManagerReload(manager: ResourceManager) { |
| 85 | + // Check for a server running, this is due to the create a world screen triggering datapack reloads, these are fine to happen as many times as needed as players may be in the process of adding their datapacks. |
| 86 | + val isInGame = server() != null |
| 87 | + if (isInGame && this.type == PackType.SERVER_DATA && !INSTANCE.canReload) { |
| 88 | + return |
| 89 | + } |
| 90 | + |
| 91 | + registries.stream().filter { it: DataRegistry? -> it!!.type == this.type } |
| 92 | + .forEach { it: DataRegistry? -> it!!.reload(manager) } |
| 93 | + if (isInGame && this.type == PackType.SERVER_DATA) { |
| 94 | + canReload = false |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + fun type(): PackType { |
| 99 | + return type |
| 100 | + } |
| 101 | + |
| 102 | + override fun equals(obj: Any?): Boolean { |
| 103 | + if (obj === this) return true |
| 104 | + if (obj == null || obj.javaClass != this.javaClass) return false |
| 105 | + val that = obj as SimpleResourceReloader |
| 106 | + return this.type == that.type |
| 107 | + } |
| 108 | + |
| 109 | + override fun hashCode(): Int { |
| 110 | + return Objects.hash(type) |
| 111 | + } |
| 112 | + |
| 113 | + override fun toString(): String { |
| 114 | + return "SimpleResourceReloader[" + |
| 115 | + "type=" + type + ']' |
| 116 | + } |
| 117 | + } |
| 118 | + |
| 119 | + companion object { |
| 120 | + @JvmField |
| 121 | + val INSTANCE: GenerationsDataProvider = GenerationsDataProvider() |
| 122 | + } |
| 123 | +} |
0 commit comments