diff --git a/README.md b/README.md index 317003e2a..3c71047ed 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A Minecraft mod about superability. The inspiration of AcademyCraft comes from [A Certain Scientific Railgun (とある科学の超電磁砲)](https://en.wikipedia.org/wiki/A_Certain_Scientific_Railgun) but the mod content is not limited of the background. -Visit [AcademyCraft's Website](http://ac.li-dev.cn/) to get the latest release and know more about it. +Visit [AcademyCraft's Website](https://ac.li-dev.cn/) to get the latest release and know more about it. Issue(Idea, Bug) Submission ============ diff --git a/build.gradle b/build.gradle index 7ad931445..da18b97b9 100644 --- a/build.gradle +++ b/build.gradle @@ -99,7 +99,7 @@ repositories { configurations { provided shade - compile.extendsFrom shade + deobfCompile.extendsFrom shade } // sourceSets.main.compileClasspath += [configurations.provided] @@ -112,7 +112,10 @@ idea { dependencies { - deobfCompile "cn.lambdalib2:LambdaLib2:${config.lambdalib_ver}" + // Shade dependencies + shade "cn.lambdalib2:LambdaLib2:${config.lambdalib_ver}" + + // Optional dependencies deobfCompile "codechicken:CodeChickenLib:1.12.2-${config.ccl_ver}:universal" deobfCompile "mezz.jei:jei_1.12.2:4.8.0.119" //deobfCompile "codechicken:NotEnoughItems:1.12.2-${config.nei_ver}:universal" @@ -167,14 +170,24 @@ compileScala.options.encoding = "UTF-8" task deobfJar(type: Jar, dependsOn: 'jar') { classifier 'dev' from sourceSets.main.output + manifest { + attributes 'FMLCorePluginContainsFMLMod' : 'true' + attributes 'FMLCorePlugin' : 'cn.lambdalib2.CorePlugin' + } } jar { configurations.shade.each { dep -> from(project.zipTree(dep)){ exclude 'META-INF', 'META-INF/**' + exclude 'mcmod.info' + exclude 'pack.mcmeta' } } + manifest { + attributes 'FMLCorePluginContainsFMLMod' : 'true' + attributes 'FMLCorePlugin' : 'cn.lambdalib2.CorePlugin' + } } // http://www.minecraftforge.net/forum/topic/36791-trying-to-shade-dependencies-into-jar/ diff --git a/build.properties b/build.properties index bb2f71b23..686244846 100644 --- a/build.properties +++ b/build.properties @@ -1,5 +1,5 @@ mod_name = AcademyCraft -mod_ver = 1.1.1 +mod_ver = 1.1.2 mod_group = cn.academy mc_ver = 1.12.2 forge_ver = 14.23.4.2705-1.12.2 @@ -7,6 +7,6 @@ forge_ver = 14.23.4.2705-1.12.2 nei_ver = 2.4.1.233 ccl_ver = 3.1.8.341 -lambdalib_ver = 0.1.8 +lambdalib_ver = 0.1.9 diff --git a/src/main/java/cn/academy/AcademyCraft.java b/src/main/java/cn/academy/AcademyCraft.java index 0309d968f..44c2507c8 100644 --- a/src/main/java/cn/academy/AcademyCraft.java +++ b/src/main/java/cn/academy/AcademyCraft.java @@ -1,6 +1,6 @@ package cn.academy; -import cn.academy.analyticUtil.AnalyticDataListener; +import cn.academy.analytic.AnalyticDataListener; import cn.lambdalib2.crafting.CustomMappingHelper; import cn.lambdalib2.crafting.RecipeRegistry; import cn.lambdalib2.registry.RegistryMod; @@ -72,7 +72,7 @@ public ItemStack createIcon() { private static void preInit(FMLPreInitializationEvent event) { log.info("Starting AcademyCraft"); log.info("Copyright (c) Lambda Innovation, 2013-2018"); - log.info("http://ac.li-dev.cn/"); + log.info("https://ac.li-dev.cn/"); recipes = new RecipeRegistry(); config = new Configuration(event.getSuggestedConfigurationFile()); diff --git a/src/main/java/cn/academy/ability/context/ContextManager.java b/src/main/java/cn/academy/ability/context/ContextManager.java index f7590c59d..5c00e7027 100644 --- a/src/main/java/cn/academy/ability/context/ContextManager.java +++ b/src/main/java/cn/academy/ability/context/ContextManager.java @@ -2,7 +2,7 @@ import cn.academy.AcademyCraft; import cn.academy.ability.context.Context.Status; -import cn.academy.analyticUtil.events.AnalyticSkillEvent; +import cn.academy.analytic.events.AnalyticSkillEvent; import cn.academy.event.ability.CategoryChangeEvent; import cn.academy.event.ability.OverloadEvent; import cn.lambdalib2.s11n.network.NetworkMessage; diff --git a/src/main/java/cn/academy/ability/vanilla/teleporter/skill/Flashing.java b/src/main/java/cn/academy/ability/vanilla/teleporter/skill/Flashing.java index 35fee346b..5368e2101 100644 --- a/src/main/java/cn/academy/ability/vanilla/teleporter/skill/Flashing.java +++ b/src/main/java/cn/academy/ability/vanilla/teleporter/skill/Flashing.java @@ -19,6 +19,8 @@ import cn.lambdalib2.util.Raytrace; import cn.lambdalib2.util.VecUtils; import com.google.common.base.Preconditions; +import net.minecraft.client.Minecraft; +import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundCategory; @@ -28,7 +30,6 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import org.lwjgl.input.Keyboard; import java.util.Optional; @@ -136,7 +137,15 @@ void localMakeAlive() { clientRuntime().addActivateHandler(activateHandler); final String[] strs = new String[] { null, "a", "d", "w", "s"}; - final int[] keys = new int[] { -1, Keyboard.KEY_A, Keyboard.KEY_D, Keyboard.KEY_W, Keyboard.KEY_S }; + Minecraft mc = Minecraft.getMinecraft(); + GameSettings settings = mc.gameSettings; + final int[] keys = new int[] { + -1, + settings.keyBindLeft.getKeyCode(), + settings.keyBindRight.getKeyCode(), + settings.keyBindForward.getKeyCode(), + settings.keyBindBack.getKeyCode() + }; for (int i = 0; i < 4; ++i) { final int localid = i + 1; clientRuntime().addKey(KEY_GROUP, keys[localid], new KeyDelegate() { diff --git a/src/main/java/cn/academy/analyticUtil/AnalyticDataListener.java b/src/main/java/cn/academy/analytic/AnalyticDataListener.java similarity index 83% rename from src/main/java/cn/academy/analyticUtil/AnalyticDataListener.java rename to src/main/java/cn/academy/analytic/AnalyticDataListener.java index 7882447de..8100785fd 100644 --- a/src/main/java/cn/academy/analyticUtil/AnalyticDataListener.java +++ b/src/main/java/cn/academy/analytic/AnalyticDataListener.java @@ -1,8 +1,8 @@ -package cn.academy.analyticUtil; +package cn.academy.analytic; import cn.academy.AcademyCraft; -import cn.academy.analyticUtil.events.AnalyticLevelUpEvent; -import cn.academy.analyticUtil.events.AnalyticSkillEvent; +import cn.academy.analytic.events.AnalyticLevelUpEvent; +import cn.academy.analytic.events.AnalyticSkillEvent; import cn.academy.datapart.AbilityData; import cn.academy.event.ability.LevelChangeEvent; import cn.academy.event.ability.SkillLearnEvent; @@ -21,9 +21,12 @@ import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.TimeZone; // Collects some **anonymous** analytics data // What we collect: a unique hash of user, location, in-mod action (Level-up, use ability, etc.) @@ -47,12 +50,16 @@ private AnalyticDataListener(){ @SubscribeEvent public void loginListener(PlayerEvent.PlayerLoggedInEvent event){ - String serverIp = getCurrentIPinfo(); + Thread delaySender = new DelaySender(event.player); + delaySender.start();//avoid sending message to the client thread before it hasn't been initialized + } + + public void serverGetter(EntityPlayer player,String serverIp){ if(null==serverSource) { serverSource = new AnalyticDto(); serverSource.setVersion(AcademyCraft.VERSION); serverSource.setUuidName("server"); - serverSource.setStartTime(new Date().getTime()); + serverSource.setStartTime(UTCZeroTime()); String[] ipArray =serverIp.split(" "); if (ipArray.length < 6) { serverSource.initNaNIPInfo(); @@ -63,7 +70,7 @@ public void loginListener(PlayerEvent.PlayerLoggedInEvent event){ serverSource.setCity(ipArray[5]); } } - NetworkMessage.sendTo(event.player,this,CHANNEL,event.player,serverIp); + NetworkMessage.sendTo(player,this,CHANNEL,player,serverIp); } //on Client @@ -88,7 +95,7 @@ public void serverIpCollector(String ipInfo,EntityPlayer player,Boolean isServer AnalyticDto playerData = new AnalyticDto(); playerData.setVersion(AcademyCraft.VERSION); playerData.setUuidName(SHA(player.getUniqueID()+player.getName())); - playerData.setStartTime(new Date().getTime()); + playerData.setStartTime(UTCZeroTime()); String[] ipArray = ipInfo.split(" "); if (ipArray.length < 6) { playerData.initNaNIPInfo(); @@ -153,11 +160,12 @@ public void skillLearnListener(SkillLearnEvent event){ } //get ip info - private String getCurrentIPinfo(){ + public String getCurrentIPinfo(){ String ipInfo = ""; try { URL object = new URL("https://myip.ipip.net"); HttpURLConnection con = (HttpURLConnection)object.openConnection(); + con.setRequestProperty("User-Agent",""); BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8)); String line = null; StringBuilder sb = new StringBuilder(); @@ -199,4 +207,31 @@ private String SHA(final String strText){ return strResult; } + private long UTCZeroTime(){ + SimpleDateFormat df =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + df.setTimeZone(TimeZone.getTimeZone("GMT+0:00")); + String currDate = df.format(new Date()); + Timestamp timestamp = Timestamp.valueOf(currDate); + return timestamp.getTime(); + } + +} + +class DelaySender extends Thread{ + private EntityPlayer player; + private String serverIp; + DelaySender(EntityPlayer player){ + this.player=player; + this.serverIp=serverIp; + } + @Override + public void run() { + try { + Thread.sleep(10000); + serverIp = AcademyCraft.analyticDataListener.getCurrentIPinfo(); + AcademyCraft.analyticDataListener.serverGetter(player,serverIp); + }catch (Exception e){ + e.printStackTrace(); + } + } } diff --git a/src/main/java/cn/academy/analyticUtil/AnalyticDto.java b/src/main/java/cn/academy/analytic/AnalyticDto.java similarity index 98% rename from src/main/java/cn/academy/analyticUtil/AnalyticDto.java rename to src/main/java/cn/academy/analytic/AnalyticDto.java index 128849b70..c806740a4 100644 --- a/src/main/java/cn/academy/analyticUtil/AnalyticDto.java +++ b/src/main/java/cn/academy/analytic/AnalyticDto.java @@ -1,4 +1,4 @@ -package cn.academy.analyticUtil; +package cn.academy.analytic; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/cn/academy/analyticUtil/AnalyticInfoSender.java b/src/main/java/cn/academy/analytic/AnalyticInfoSender.java similarity index 95% rename from src/main/java/cn/academy/analyticUtil/AnalyticInfoSender.java rename to src/main/java/cn/academy/analytic/AnalyticInfoSender.java index 8d57b36a7..cf37c5522 100644 --- a/src/main/java/cn/academy/analyticUtil/AnalyticInfoSender.java +++ b/src/main/java/cn/academy/analytic/AnalyticInfoSender.java @@ -1,4 +1,4 @@ -package cn.academy.analyticUtil; +package cn.academy.analytic; import cn.academy.AcademyCraft; import com.google.gson.Gson; @@ -26,7 +26,7 @@ public void linkStart(Map sourceMap){ class AnalysisTask extends TimerTask{ private Map sourceMap; - private String voidclRBQ="http://144.34.208.247:8080/lambda/data/listener"; + private String voidclRBQ="https://ac.li-dev.cn/analytics"; AnalysisTask(Map sourceMap){ this.sourceMap=sourceMap; } diff --git a/src/main/java/cn/academy/analyticUtil/events/AnalyticLevelUpEvent.java b/src/main/java/cn/academy/analytic/events/AnalyticLevelUpEvent.java similarity index 92% rename from src/main/java/cn/academy/analyticUtil/events/AnalyticLevelUpEvent.java rename to src/main/java/cn/academy/analytic/events/AnalyticLevelUpEvent.java index edd7a4177..7b32d5b7c 100644 --- a/src/main/java/cn/academy/analyticUtil/events/AnalyticLevelUpEvent.java +++ b/src/main/java/cn/academy/analytic/events/AnalyticLevelUpEvent.java @@ -1,4 +1,4 @@ -package cn.academy.analyticUtil.events; +package cn.academy.analytic.events; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.fml.common.eventhandler.Event; diff --git a/src/main/java/cn/academy/analyticUtil/events/AnalyticSkillEvent.java b/src/main/java/cn/academy/analytic/events/AnalyticSkillEvent.java similarity index 94% rename from src/main/java/cn/academy/analyticUtil/events/AnalyticSkillEvent.java rename to src/main/java/cn/academy/analytic/events/AnalyticSkillEvent.java index c50efa73e..b67e1f350 100644 --- a/src/main/java/cn/academy/analyticUtil/events/AnalyticSkillEvent.java +++ b/src/main/java/cn/academy/analytic/events/AnalyticSkillEvent.java @@ -1,4 +1,4 @@ -package cn.academy.analyticUtil.events; +package cn.academy.analytic.events; import cn.academy.ability.Skill; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/cn/academy/client/auxgui/TerminalUI.java b/src/main/java/cn/academy/client/auxgui/TerminalUI.java index 57647bbdc..ac86c38a8 100644 --- a/src/main/java/cn/academy/client/auxgui/TerminalUI.java +++ b/src/main/java/cn/academy/client/auxgui/TerminalUI.java @@ -2,6 +2,7 @@ import cn.academy.Resources; import cn.academy.client.sound.ACSounds; +import cn.academy.terminal.DonatorList; import cn.academy.util.RegACKeyHandler; import cn.academy.terminal.App; import cn.academy.terminal.AppEnvironment; @@ -105,6 +106,10 @@ public void onEnable() { KeyManager.dynamic.addKeyHandler("terminal_click",KeyManager.MOUSE_LEFT, clickHandler = new LeftClickHandler()); ControlOverrider.override(OVERRIDE_GROUP, KeyManager.MOUSE_LEFT); + + // There is a chance that About App will be opened + // to improve user experience we request that ahead of time + DonatorList.Instance.tryRequest(); } @Override diff --git a/src/main/java/cn/academy/datapart/AbilityData.java b/src/main/java/cn/academy/datapart/AbilityData.java index 87a1b713e..9603c24dd 100644 --- a/src/main/java/cn/academy/datapart/AbilityData.java +++ b/src/main/java/cn/academy/datapart/AbilityData.java @@ -4,7 +4,7 @@ import cn.academy.ability.Category; import cn.academy.ability.CategoryManager; import cn.academy.ability.Skill; -import cn.academy.analyticUtil.events.AnalyticLevelUpEvent; +import cn.academy.analytic.events.AnalyticLevelUpEvent; import cn.academy.event.ability.*; import cn.lambdalib2.datapart.DataPart; import cn.lambdalib2.datapart.EntityData; diff --git a/src/main/java/cn/academy/terminal/DonatorList.java b/src/main/java/cn/academy/terminal/DonatorList.java new file mode 100644 index 000000000..dece972ef --- /dev/null +++ b/src/main/java/cn/academy/terminal/DonatorList.java @@ -0,0 +1,80 @@ +package cn.academy.terminal; + +import cn.academy.AcademyCraft; +import cn.lambdalib2.util.Debug; +import com.google.gson.Gson; +import net.minecraft.client.Minecraft; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.Event; +import org.apache.commons.io.IOUtils; + +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.Collections; +import java.util.List; + +public enum DonatorList { + Instance; + + List _donators = Collections.emptyList(); + + final Gson _gson = new Gson(); + + volatile boolean _requesting = false; + + public boolean isLoaded() { + return _donators.size() > 0; + } + + private class Attributes { + public List list; + } + + private class ResponseData { + public boolean success; + public Attributes attributes; + } + + public List getList() { + return _donators; + } + + public void tryRequest() { + if (!isLoaded() && !_requesting) { + _requesting = true; + new Thread(() -> { + try { + String url = "https://ac.li-dev.cn/donators"; + URLConnection con = new URL(url).openConnection(); + con.setDoInput(true); + + InputStream is = con.getInputStream(); + String text = IOUtils.toString(is, "UTF-8"); + ResponseData rsp = _gson.fromJson(text, ResponseData.class); + + if (rsp.success) { + Debug.assertNotNull(rsp.attributes); + Debug.assertNotNull(rsp.attributes.list); + + // Acknowledge the result in CLIENT thread + Minecraft.getMinecraft().addScheduledTask(() -> { + _donators = rsp.attributes.list; + MinecraftForge.EVENT_BUS.post(new DonatorListRefreshEvent()); + }); + } else { + Debug.error("AcademyCraft failed when requesting donator list."); + if (AcademyCraft.DEBUG_MODE) + Debug.error("Rsp str: " + text); + } + } catch (Exception e) { + if (AcademyCraft.DEBUG_MODE) + Debug.error(e); + } + _requesting = false; + }).start(); + } + } + + public static class DonatorListRefreshEvent extends Event {} +} diff --git a/src/main/java/cn/academy/terminal/app/AppAbout.java b/src/main/java/cn/academy/terminal/app/AppAbout.java index 75b57d6a5..10b78cd94 100644 --- a/src/main/java/cn/academy/terminal/app/AppAbout.java +++ b/src/main/java/cn/academy/terminal/app/AppAbout.java @@ -3,6 +3,8 @@ import cn.academy.Resources; import cn.academy.terminal.App; import cn.academy.terminal.AppEnvironment; +import cn.academy.terminal.DonatorList; +import cn.academy.terminal.DonatorList.DonatorListRefreshEvent; import cn.academy.terminal.RegApp; import cn.lambdalib2.cgui.CGuiScreen; import cn.lambdalib2.cgui.Widget; @@ -26,6 +28,8 @@ import com.typesafe.config.ConfigValue; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.I18n; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.lwjgl.input.Mouse; @@ -229,6 +233,14 @@ enum TabType { Credits, Donate } }); onTabTypeChanged(TabType.Credits); + DonatorList.Instance.tryRequest(); + MinecraftForge.EVENT_BUS.register(this); + } + + @Override + public void onGuiClosed() { + super.onGuiClosed(); + MinecraftForge.EVENT_BUS.unregister(this); } private void initTexts() { @@ -276,7 +288,8 @@ private void initTexts() { y += 1.5f * FontSize; - List donators = root.getStringList("donators"); + List donators = DonatorList.Instance.isLoaded() ? + DonatorList.Instance.getList() : root.getStringList("donators"); Collections.shuffle(donators); // Randomize the list for (int i = 0; i < donators.size(); ++i) { float tw = 150, margin = 30; @@ -348,6 +361,11 @@ public void handleMouseInput() throws IOException { } } + @SubscribeEvent + public void onDonatorListRefresh(DonatorListRefreshEvent e) { + initTexts(); + } + private void onTabTypeChanged(TabType type) { _tabType = type; setTabButtonEnable(_btnCredits, _tabType == TabType.Credits); diff --git a/src/main/resources/assets/academy/config/about.conf b/src/main/resources/assets/academy/config/about.conf index ace1fcbb2..212a66d82 100644 --- a/src/main/resources/assets/academy/config/about.conf +++ b/src/main/resources/assets/academy/config/about.conf @@ -43,8 +43,9 @@ credits { ], [ "Localization", - "mkpoli", - "柳荫理乃" + "mkpoli (Japanese)", + "柳荫理乃 (Japanese)", + "dtraitor (Russian)" ], [ "GitHub Contributors", @@ -54,6 +55,7 @@ credits { "berry64", ] ] + // ! This list is not being maintained anymore and only serves as a fallback. donators: [ // patreon "anon katon", @@ -157,7 +159,7 @@ donation { zh_cn: [ "很高兴你能体验AcademyCraft,希望你玩的开心!", "如果你喜欢AC的话,可以通过捐助来支持我们的开发!", - "!!点这里支持我们|http://ac.li-dev.cn/捐助", + "!!点这里支持我们|https://ac.li-dev.cn/捐助", "我们会以更多更有趣的游戏内容作为回报的!=3=", "", "", diff --git a/src/main/resources/assets/academy/lang/en_us.lang b/src/main/resources/assets/academy/lang/en_us.lang index 37bdb9ebf..ac2b44cf9 100644 --- a/src/main/resources/assets/academy/lang/en_us.lang +++ b/src/main/resources/assets/academy/lang/en_us.lang @@ -497,4 +497,4 @@ ac.converter.desc_template=Converts %s to %s ac.skill_tree.dev_developing=Developing... # About App -ac.about.donators_info=In no particular order\nThe list will be updated once a version +ac.about.donators_info=In no particular order diff --git a/src/main/resources/assets/academy/lang/ru_ru.lang b/src/main/resources/assets/academy/lang/ru_ru.lang new file mode 100644 index 000000000..a55f37774 --- /dev/null +++ b/src/main/resources/assets/academy/lang/ru_ru.lang @@ -0,0 +1,498 @@ +# AcademyCraft Russian Language file +# This file is mainly categorized by use (except for those which needs to follow the rules of Minecraft). + +# Common +itemGroup.AcademyCraft=AcademyCraft +ac.data_config_parse_fail=[AcademyCraft] Failed to parse custom config data file. The error: + +# Item +item.ac_crystal_low.name=Кристалл низкой имаг частоты +item.ac_crystal_normal.name=Кристалл средней имаг частоты +item.ac_crystal_pure.name=Кристалл высокой имаг частоты +item.ac_constraint_ingot.name=Слиток ограниченого металла +item.ac_constraint_plate.name=Пластина ограниченого металла +item.ac_imag_silicon_ingot.name=Кремниевый имаг слиток +item.ac_wafer.name=Кремниевая имаг вафля +item.ac_imag_silicon_piece.name=Кусок имаг кремния +item.ac_reso_crystal.name=Резонирующий кристалл + +item.ac_brain_component.name=Анализатор мозговых волн +item.ac_info_component.name=Обработчик информации +item.ac_reinforced_iron_plate.name=Укрепленная железная пластина +item.ac_resonance_component.name=Резонатор +item.ac_energy_convert_component.name=Преобразователь энергии +item.ac_calc_chip.name=Вычислительный чип +item.ac_data_chip.name=Чип данных + +item.ac_matter_unit.name=Материальная единица +item.ac_matter_unit_phase_liquid.name=Жидкая имаг материальная единица +item.ac_matter_unit_none.name=Пустая единица +item.ac_matrix_core.name=Матричное ядро +item.ac_mat_core_0.name=Базовоя матричное ядро +item.ac_mat_core_1.name=Улучшеное матричное ядро +item.ac_mat_core_2.name=Продвинутое матричное ядро +item.ac_energy_unit.name=Энергетическая кдиницв +item.ac_windgen_fan.name=Ротор ветрогенератора + +item.ac_coin.name=Монета +item.ac_silbarn.name=Что-то кремниевое +item.ac_needle.name=Игла +item.ac_mag_hook.name=Магнитный крюк + +item.ac_terminal_installer.name=Терминал данных +item.ac_apps.name=Установщик приложений + +item.ac_developer_portable.name=Портативный производитель +item.ac_magnetic_coil.name=Магнитная катушка высокого напряжения +item.ac_magnetic_coil.desc=Заряжает разработчика
Для того, чтобы переписать личную реальность +item.ac_induction_factor.name=Коэфициент индукционной способности +item.ac_tutorial.name=Терминал MisakaCloud + +# Block +tile.ac_constraint_metal.name=Ограниченая металлическая руда +tile.ac_crystal_ore.name=Имаг кристалическая руда +tile.ac_imagsil_ore.name=Имаг кремниевая руда +tile.ac_reso_ore.name=Резонирующая кристальная руда +tile.ac_machine_frame.name=Машинный корпус + +tile.ac_imag_phase.name=Переходник в имаг жидкость + +tile.ac_imag_fusor.name=Имаг Термоблок +tile.ac_matrix.name=Беспроводная Имаг Матрица +tile.ac_node_basic.name=Базовая беспроводная имаг нода +tile.ac_node_standard.name=Улучшеная беспроводная имаг нода +tile.ac_node_advanced.name=Продвинутая беспроводная имаг нода +tile.ac_metal_former.name=Металло формировщик +tile.ac_solar_gen.name=Солнечный генератор +tile.ac_cat_engine.name=Кот и Тост +tile.ac_phase_gen.name=Фазовый генератор +tile.ac_windgen_base.name=Основа столба ветрогенератора +tile.ac_windgen_pillar.name=Столб ветрогенератора +tile.ac_windgen_main.name=Ветрогенератор +tile.ac_eu_output.name=Енергентический мост (IC2 EU Выходит) +tile.ac_eu_input.name=Енергентический мост (IC2 EU Входит) +tile.ac_rf_output.name=Енергентический мост (CoFH RF Выходит) +tile.ac_rf_input.name=Енергентический мост (CoFH RF Входит) +tile.ac_dev_normal.name=Разработчик нормальных способностей +tile.ac_dev_advanced.name=Разработчик продвинутых способностей +tile.ac_ability_interferer.name=Умение мешать (я сам хз) + +# Data Terminal +ac.terminal.notinstalled=Вы еще не установили Терминал Данных. +ac.terminal.alrdy_installed=Вы уже установили Терминал Данных. +ac.terminal.key_hint=Терминал Данных успешно установлен. Используйте кнопку %s что-бы открыть/закрыть интерфейс +ac.gui.terminal.installing= Установка... +ac.gui.terminal.appcount=%d Приложений + +ac.terminal.app_alrdy_installed=Вы уже установили приложение %s. +ac.terminal.app_installed=Вы успешно установили приложение %s. + +# Apps +ac.app.skill_tree.name=Древо Умений +ac.app.knowledge_record.name=Записыватель жизни +ac.app.settings.name=Настройки +ac.app.media_player.name=Медиа проигрыватель +ac.app.tutorial.name=MisakaCloud +ac.app.about.name=Информация + +ac.app.freq_transmitter.name=Передатчик частот +ac.app.freq_transmitter.s0_0=Пожалуйста, щелкните правой кнопкой мыши на беспроводной матрице или узле, чтобы начать устанавливать связь с. +ac.app.freq_transmitter.s1_0=Нажмите ENTER что-бы продолжить +ac.app.freq_transmitter.s1_1=Авторизация... +ac.app.freq_transmitter.s2_0=Щелкните правой кнопкой мыши на любом беспроводном узле поблизости, чтобы установить связь. Нажмите на любые другие блоки, чтобы выйти. +ac.app.freq_transmitter.s3_0=Щелкните правой кнопкой мыши по любому беспроводному приемнику или генераторе поблизости, чтобы добавить ссылку. Нажмите на любые другие блоки, чтобы выйти. +ac.app.freq_transmitter.st=Время действия вышло. + +ac.app.freq_transmitter.e0=Беспроводная матрица не инициализирована. +ac.app.freq_transmitter.e1=Ошибка авторизации. +ac.app.freq_transmitter.e2=Соеденение прервано. Возможно, матрица достигла своей емкости или сигнал находится вне диапазона. +ac.app.freq_transmitter.e3=Соеденение прервано. Возможно, нода достигла своей емкости или сигнал находится вне диапазона. +ac.app.freq_transmitter.e4=Действие отменено. +ac.app.freq_transmitter.e5=Передача... +ac.app.freq_transmitter.e6=Соеденение успешно. + +## Settings App +ac.settings.cat.generic=Общие +ac.settings.prop.attackPlayer=Включить PvP +ac.settings.prop.destroyBlocks=Уничтожать блоки +ac.settings.prop.headsOrTails=Играть в головы или хвосты (Автор нарк) +ac.settings.prop.useMouseWheel=Колесо мыши регулирует расстояние телепортации +#Use mouse wheel to adjust Penetrate Teleport distance + +ac.settings.cat.keys=Клавиши +ac.settings.prop.ability_activation=Активировать способность +ac.settings.prop.edit_preset=Редактировать пресет +ac.settings.prop.switch_preset=Переключить пресет +ac.settings.prop.open_data_terminal=Открыть Терминал Данных +ac.settings.prop.ability_0=Способность #1 +ac.settings.prop.ability_1=Способность #2 +ac.settings.prop.ability_2=Способность #3 +ac.settings.prop.ability_3=Способность #4 +ac.settings.prop.debug_console=Дебаг Консоль + +ac.settings.cat.misc=Остальное +ac.settings.prop.edit_ui=Кастомизировать Интерфейс + +## Media App +## -> ac.app.media.* +ac.media.acquired=Вы установили медиа-файл %s +ac.media.haveone=Вы уже установили медиа-файл %s +ac.media.notinstalled=Вы еще не установили Медиа Проигрователь. + +### Medias +ac.media.only_my_railgun.name=only my railgun +ac.media.only_my_railgun.desc=Toaru Kagaku no Railgun OP1 +ac.media.level5_judgelight.name=LEVEL5-judgelight- +ac.media.level5_judgelight.desc=Toaru Kagaku no Railgun OP2 +ac.media.sisters_noise.name=sister's noise +ac.media.sisters_noise.desc=Toaru Kagaku no Railgun S OP1 + +# Ability Generic +ac.ability.level0=Уровень 0 +ac.ability.level1=Уровень 1 +ac.ability.level2=Уровень 2 +ac.ability.level3=Уровень 3 +ac.ability.level4=Уровень 4 +ac.ability.level5=Уровень 5 + +death.attack.ac_skill=%1$s был убит %2$s припомощи %3$s + +ac.activate_key.deactivate.desc=Деактивировать способность +ac.activate_key.endspecial.desc=Завершить режим специальных навыков +ac.activate_key.endskill.desc=Откатить умение + +ac.gui.preset_edit.name=Редактировать премет +ac.gui.preset_edit.tag=Пресет # +ac.gui.preset_edit.skill_remove=Удалить текущий +ac.gui.preset_edit.skill_select=Выбрать умение + +## Generic Skills +ac.ability.generic.brain_course.name=Мозговой курс +ac.ability.generic.brain_course_advanced.name=Продвинутый курс мозга +ac.ability.generic.mind_course.name=Курс разума (Внимания, может духа) +ac.ability.generic.brain_course.desc=Uпройти тренировку для вашего мозга. Увеличивает Макс. CP на 1000. +ac.ability.generic.brain_course_advanced.desc=Развивть мыслительные способности вашего мозга глубже. Увеличивает Макс. CP на 1000 и Макс. Перегрузку на 100. +ac.ability.generic.mind_course.desc=Узнайте, как лучше расслабить свой мозг. Ускоряет восстановление CP на 20 %%. + +## Electromaster +ac.ability.electromaster.name=Электромастер + +### EM Skills +ac.ability.electromaster.arc_gen.name=Генерация дуги +ac.ability.electromaster.mag_manip.name=Магнитные манипуляции +ac.ability.electromaster.mine_detect.name=Обнаружение мин +ac.ability.electromaster.railgun.name=Рейлган +ac.ability.electromaster.mag_movement.name=Магнитное движение +ac.ability.electromaster.iron_sand.name=Контрль железного песка +ac.ability.electromaster.iron_sand.sword.name=Меч из железного песка +ac.ability.electromaster.iron_sand.whip.name=Кнут из железного песка +ac.ability.electromaster.iron_sand.storm.name=Буря из железного песка +ac.ability.electromaster.iron_sand.cone.name=Конус из железного песка +ac.ability.electromaster.charging.name=Текущая зарядка +ac.ability.electromaster.body_intensify.name=Активизировать тело +ac.ability.electromaster.thunder_clap.name=Удар грома +ac.ability.electromaster.thunder_bolt.name=Молния + +ac.ability.electromaster.arc_gen.desc=Вызывает слабую электрическую дугу, которая наносит небольшой урон по области, которую она поражает. Если он непосредственно попадет на огнеопасный блок, у него будет шанс его зажечь. +ac.ability.electromaster.mag_manip.desc=Управляйте и перемещайте намагничиваемые предметы с помощью магнитной силы, даже выбрасывайте их, чтобы повредить врагов. +ac.ability.electromaster.mine_detect.desc=Закройте глаза и почувствуйте поток магнетизма, позволяющий увидеть намеки на драгоценные минеральные ресурсы вокруг вас. +ac.ability.electromaster.railgun.desc=Стреляйте монетой на высокой скорости с помощью электромагнитной индукции. Причиняет разрушительный ущерб там, где она воздействует. +ac.ability.electromaster.mag_movement.desc=Создайте сильное магнитное поле и притяните себя к какой-нибудь магнитной цели. Чрезвычайно полезен при движении или побеге. +ac.ability.electromaster.iron_sand.desc=Отделите железо от песка и управляйте им, чтобы создать изменчивый и опасный эффект атаки. +ac.ability.electromaster.charging.desc=Генерирует электрический ток для зарядки вещи в вашей руке или электрических блоков в мире. +ac.ability.electromaster.body_intensify.desc=Точно настройте биоэлектричество, чтобы улучшить свои физические способности на короткое время. +ac.ability.electromaster.thunder_clap.desc=Управляйте магнитным полем в атмосфере, создавая грозовые тучи, и направляйте электричество вниз, чтобы вызвать разрушительный удар молнии. +ac.ability.electromaster.thunder_bolt.desc=Сжимает огромное количество электричества в мощный болт, взрываясь и повреждая что-либо в его области. + +## Teleporter +ac.ability.teleporter.name=Телепортер + +### TP Skills +ac.ability.teleporter.threatening_teleport.name=Угрожающий Телепорт +ac.ability.teleporter.dim_folding_theorem.name=Размерная теорема складывания +ac.ability.teleporter.penetrate_teleport.name=Проникающий телепорт +ac.ability.teleporter.mark_teleport.name=Телепортация по метке +ac.ability.teleporter.flesh_ripping.name=Разрывание плоти +ac.ability.teleporter.location_teleport.name=Телепорт по локации +ac.ability.teleporter.shift_tp.name=Телепортационный сдвиг +ac.ability.teleporter.space_fluct.name=Колебания пространства +ac.ability.teleporter.flashing.name=Мигание + +ac.ability.teleporter.threatening_teleport.desc=Телепортируйте предметы куда-то вокруг вас. Иногда даже маленький фрагмент способен убить врага. +ac.ability.teleporter.dim_folding_theorem.desc=Увеличьте свой урон против врагов, создавая крошечный феномен складывания пространства. +ac.ability.teleporter.penetrate_teleport.desc=Определите толщину препятствия перед вами и телепортируйтесь прямо через него. +ac.ability.teleporter.mark_teleport.desc=Отмечает, куда вы смотрите как пункт назначения, и телепортирует вас туда. +ac.ability.teleporter.flesh_ripping.desc=Разорвите внутри вашего врага и нанесите кровавый урон. Чрезмерно кровавый эффект может вызвать у вас дискомфорт. +ac.ability.teleporter.location_teleport.desc=Запомните ваше текущее местоположение и телепортируйтесь обратно из любого места, которое будет дальше. +ac.ability.teleporter.shift_tp.desc=Телепортируйте блок по кординатной прямой. На пуьи блок повредит сущность +ac.ability.teleporter.space_fluct.desc=Усильте свою способность складывать пространство, чтобы наносить более опасный критический урон. +ac.ability.teleporter.flashing.desc=Используйте несколько телепортаций за короткое время, чтобы маневрировать по воздуху. +ac.ability.teleporter.crithit=%fx критический удар! + +ac.gui.loctele.err_exp=Слишком мало опыта, немогу пройти измерение +ac.gui.loctele.err_cp=CP недостаточно, немогу телепортироватся + +## Meltdowner +ac.ability.meltdowner.name=Плавитель + +### MD Skills +ac.ability.meltdowner.electron_bomb.name=Бомьа из электронов +ac.ability.meltdowner.rad_intensify.name=β Радиационная интенсивность +ac.ability.meltdowner.ray_barrage.name=Спектр лучей +ac.ability.meltdowner.scatter_bomb.name=Касетные бомбы +ac.ability.meltdowner.meltdowner.name=Плавитель +ac.ability.meltdowner.light_shield.name=Молниеносный щит +ac.ability.meltdowner.jet_engine.name=Реактивный двигатель +ac.ability.meltdowner.mine_ray_basic.name=Базовый копательный луч +ac.ability.meltdowner.mine_ray_expert.name=Экспертный копательный луч +ac.ability.meltdowner.mine_ray_luck.name=Везучий копательный луч +ac.ability.meltdowner.electron_missile.name=Заряд электронов + +ac.ability.meltdowner.electron_bomb.desc=Соберите небольшое количество электронов, чтобы создать угрожающий луч. +ac.ability.meltdowner.rad_intensify.desc=Из-за излучения высокой интенсивности цель, пораженная лучом, вдвойне уязвима для атак в течение нескольких секунд.. +ac.ability.meltdowner.ray_barrage.desc=SВыстрелите своим высокоэнергетическим лучом в Силиконовый сарай (сам хз), чтобы рассеять его в лучевой барьер, который разрушает все перед вами. +ac.ability.meltdowner.scatter_bomb.desc=Манипулируйте более чем одной групой электронов для атаки. В результате вы не можете точно контролировать точку удара. +ac.ability.meltdowner.meltdowner.desc=Экстремальный высокоэнергетический электронный пучок, который расплавляет стены и металлы. +ac.ability.meltdowner.light_shield.desc=Формирует электроны в щит. Быстро движущиеся электроны уничтожат все, что вас атакует, и повредят все, что вас коснется. +ac.ability.meltdowner.jet_engine.desc=Используйте движущую силу электронов, запускайте себя в воздух. Создаст легкий щит, чтобы защитить вас в полете. +ac.ability.meltdowner.mine_ray_basic.desc=После долгой практики вы можете сделать свой электронный луч пригодным для сбора полезных ископаемых, не разрушая их. +ac.ability.meltdowner.mine_ray_expert.desc=Понимая, как лучше контролировать интенсивность электронов, теперь вы можете более эффективно собирать минеральные ресурсы. +ac.ability.meltdowner.mine_ray_luck.desc=После долгой практики вы можете практически полностью собрать полезные ресурсы в руде.. +ac.ability.meltdowner.electron_missile.desc=Соберите ОГРОМНОЕ количество электронов в облаке и используйте некоторые из них для атаки каждый раз. + +## Vector Manipulation +ac.ability.vecmanip.name=Векторные манипуляции + +### VM skills +ac.ability.vecmanip.dir_shock.name=Направленый шок +ac.ability.vecmanip.ground_shock.name=Шок по земле +ac.ability.vecmanip.vec_accel.name=Векторная прокрутка +ac.ability.vecmanip.vec_deviation.name=Вектор отклонение +ac.ability.vecmanip.dir_blast.name=Направленная взрывная волна +ac.ability.vecmanip.storm_wing.name=Крылья шторма +ac.ability.vecmanip.blood_retro.name=Кровавый град +ac.ability.vecmanip.vec_reflection.name=Векторная реакция +ac.ability.vecmanip.plasma_cannon.name=Плазменная пушка + +ac.ability.vecmanip.dir_shock.desc=Захватите противодействующую силу при ударе по объекту и перенаправьте его на сам объект, делая удар более мощным. +ac.ability.vecmanip.ground_shock.desc=Нанесите мощный удар по земле и направьте его вперед, который разбивает землю и запускает врагов в воздух. +ac.ability.vecmanip.vec_accel.desc=Увеличьте силу прыжка на мгновение, чтобы ускорить себя. +ac.ability.vecmanip.vec_deviation.desc=Отменяет скорость снарядов, летящих к вам, и отменяет часть боевого урона. +ac.ability.vecmanip.dir_blast.desc=Утройте силу удара в объект, делая его чрезвычайно разрушительным. Будет разбивать блоки на области, которую он поражает. +ac.ability.vecmanip.storm_wing.desc=Управляйте скоростью воздуха, чтобы сформировать четыре микро-вихря на вашей спине, и летите на высокой скорости, используя силы, которые они генерируют. Будут разбивать блоки поблизости, если неопытный. +ac.ability.vecmanip.blood_retro.desc=Размешайте кровоток органических врагов, чтобы их сосуд лопнул и умер от сильной боли. +ac.ability.vecmanip.vec_reflection.desc=Отражает опасные входящие атаки в направлении вашей прямой видимости и заставляет вашего противника выдержать это. +ac.ability.vecmanip.plasma_cannon.desc=Управляйте большой областью воздушного потока с чрезвычайной точностью, чтобы сформировать плазменное тело. Выбросьте его, чтобы вызвать катастрофический взрыв. + +# Command +ac.command.invalid=§cInvalid input, please try again. +ac.command.successful=§2Command sucessfully performed. +ac.command.notlearned=§6The player has not learned any ability yet. + +ac.command.knowledge.usage=/knowledge | [parameters...] +ac.command.knowledge.help=/knowledge help: Display the help message. +ac.command.knowledge.stat=/knowledge stat: Show statistics info of player ac.knowledge. +ac.command.knowledge.clear=/knowledge clear: Clear all knowledge info and start over again. +ac.command.knowledge.getall=/knowledge getall: Learn all knowledges right now. +ac.command.knowledge.list=/knowledge list: List all available knowledges. +ac.command.knowledge.learn=/knowledge learn [knowledge_name]: Learn some ac.knowledge. +ac.command.knowledge.unlearn=/knowledge unlearn [knowledge_name]: Unlearn some ac.knowledge. +ac.command.knowledge.stat2=Knowledge learned: %s +ac.command.knowledge.stat3=Knowledge discovered: %s +ac.command.knowledge.notfound=Knowledge with name %s doesn't exist. +ac.command.knowledge.all=All knowledges: +ac.command.knowledge.discover=/knowledge discover [knowledge_name]: Discover a specific ac.knowledge. + +ac.command.aim.usage=/aim | [parameters...] +ac.command.aim.help=/aim help: Display the help message. +ac.command.aim.cat=/aim cat [catName]: Change the specified player's categories or display the current category. +ac.command.aim.catlist=/aim catlist: List all available categories' names. +ac.command.aim.learn=/aim learn |: Learn the specified skill, regardless of its learning condition requirements. +ac.command.aim.unlearn=/aim unlearn |: Unlearn the specified skill. +ac.command.aim.learn_all=/aim learn_all: Learn all the skills. +ac.command.aim.reset=/aim reset: Clear your ability information. +ac.command.aim.learned=/aim learned: Display all currently learned skills. +ac.command.aim.skills=/aim skills: Display all skills in player's current category. +ac.command.aim.fullcp=/aim fullcp: Restore full cp of the player. +ac.command.aim.level=/aim level: Set the player's ability level. +ac.command.aim.exp=/aim exp | [exp]: Set or view the skill's experience level. +ac.command.aim.cd_clear=/aim cd_clear: Clear all skill cooldown. +ac.command.aim.nocat=Specified category not found. Use /aim catlist to list all categories. +ac.command.aim.cats=Currently available categories: +ac.command.aim.curcat=Player current category: %s +ac.command.aim.nonecat=No ability +ac.command.aim.noskill=No such skill was found. Use /aim skills to list all skills in current category. +ac.command.aim.learned.format=Learned skills: %s +ac.command.aim.curexp=Skill %s's current exp: %.0f%%. +ac.command.aim.notactive=The /aim command is currently inactive. Use /aim cheats_on or /aim cheats_off to change the active state. +ac.command.aim.warning=§cWARNING: Using /aim command will break the game balance and impact your experience about the mod, PROCEED WITH CAUTION! +ac.command.aim.outofrange=§cInput out of range: §fMust be a value between %s and %s. +ac.command.aim.invalidnum=§cInvalid number: %s. +ac.command.aim.maxout=Set current level's upgrade progress to 100%%. +ac.command.aim.nocomm=No such command was found. Use /aim help to list all commands available. +ac.command.aim.nonecathint=Ты еще не выучил никакой способности! + +ac.command.aimp.usage=/aimp | [parameters...] +ac.command.aimp.help=/aimp help: Display the help message. +ac.command.aimp.cat=/aimp cat [catName]: Change the specified player's categories or display the current category. +ac.command.aimp.catlist=/aimp catlist: List all available categories' names. +ac.command.aimp.learn=/aimp learn |: Learn the specified skill, regardless of its learning condition requirements. +ac.command.aimp.unlearn=/aimp unlearn |: Unlearn the specified skill. +ac.command.aimp.learn_all=/aimp learn_all: Learn all the skills. +ac.command.aimp.reset=/aimp reset: Clear your ability information. +ac.command.aimp.learned=/aimp learned: Display all currently learned skills. +ac.command.aimp.skills=/aimp skills: Display all skills in player's current category. +ac.command.aimp.fullcp=/aimp fullcp: Restore full cp of the player. +ac.command.aimp.level=/aimp level: Set the player's ability level. +ac.command.aimp.exp=/aimp exp | [exp]: Set or view the skill's experience level. +ac.command.aimp.cd_clear=/aimp cd_clear: Clear all skill cooldown. +ac.command.aimp.nocat=Specified category not found. Use /aimp catlist to list all categories. +ac.command.aimp.cats=Возможные сейчас категории: +ac.command.aimp.curcat=Категория игрока: %s +ac.command.aimp.nonecat=Нет способности +ac.command.aimp.noskill=No such skill was found. Use /aimp skills to list all skills in current category. +ac.command.aimp.learned.format=Выучено умение: %s +ac.command.aimp.curexp=Skill %s's опыта сейчас: %.0f%%. +ac.command.aimp.notactive=The /aimp command is currently inactive. Use /aimp cheats_on or /aimp cheats_off to change the active state. +ac.command.aimp.warning=§cWARNING: Using /aimp command will break the game balance and impact your experience about the mod, PROCEED WITH CAUTION! +ac.command.aimp.outofrange=§cЗа доступным радиусом: §fДолжно быть значение между %s и %s. +ac.command.aimp.maxout=/aimp maxout:Set current level's upgrade progress to 100%%. +ac.command.aimp.nocomm=No such command was found. Use /aimp help to list all commands available. +ac.command.aimp.nonecathint=Ты еще не выучил никакой способности! + +# Advancement +advancements.general.root=Academy Craft +advancements.general.root.desc=Начало всего +advancements.general.open_misaka_cloud=Первый контак +advancements.general.open_misaka_cloud.desc=Открыть Misaka Cloud +advancements.general.getting_phase=Мистический и мощный +advancements.general.getting_phase.desc=Получить капсулу с жидким Имагом +advancements.general.phase_generator=Новая энергия +advancements.general.phase_generator.desc=Сделать фазовый генератор +advancements.general.ac_node=Больше никаких проводов! +advancements.general.ac_node.desc=Сделать базовую беспроводную имаг ноду +advancements.general.ac_matrix=WIFI доступен тут +advancements.general.ac_matrix.desc=Сделать матрицу +advancements.general.terminal_installed=Технологии изменяют жизнь +advancements.general.terminal_installed.desc=Установить информационный терминал +advancements.general.getting_factor=Бесконечные возможности +advancements.general.getting_factor.desc=Получить фактор индукции +advancements.general.ac_developer=Лимит для людей +advancements.general.ac_developer.desc=Сделать портативный производчик способностей +advancements.general.dev_category=Над человеком +advancements.general.dev_category.desc=Сделать способнсть +advancements.general.ac_level_3=На своих двух +advancements.general.ac_level_3.desc=Улучшиться до 3 уровня +advancements.general.ac_level_5=Один в поле воин +advancements.general.ac_level_5.desc=Улучишться до 5 уровня +advancements.general.convert_category=Больше никаких случайностей +advancements.general.convert_category.desc=Изменить свою категорию +advancements.general.ac_learning_skill=Практика делает идеальным +advancements.general.ac_learning_skill.desc=Выучить любое умение +advancements.general.ac_milestone=Улучшить модуль +advancements.general.ac_milestone.desc=Достигните рубежа первого навыка +advancements.general.ac_exp_full=Сколько раз ты это сделал? +advancements.general.ac_exp_full.desc=Получи весь опыт на умении +advancements.general.ac_overload=Тут досих пор лимит на ESPов +advancements.general.ac_overload.desc=Используй свое умение пока оно не перегрузится + +# UI Commons +ac.gui.common.pg_wireless.not_connected=Не подключено +ac.gui.common.sep.info=Информация +ac.gui.common.sep.wireless_info=Беспроводная информация +ac.gui.common.sep.wireless_init=Инициализация беспроводной сети +ac.gui.common.sep.wireless_noinit=Беспроводная сеть не инициализирована +ac.gui.common.sep.change_pass=Измениит пароль +ac.gui.common.hist.energy=ЭНЕРГИЯ +ac.gui.common.hist.buffer=ЗАПАС +ac.gui.common.hist.liquid=ЖИДКОСТЬ +ac.gui.common.hist.capacity=ВМЕСТИМОСТЬ +ac.gui.common.prop.range=Длинна транспортировки +ac.gui.common.prop.owner=Владелец +ac.gui.common.prop.node_name=Имя ноды +ac.gui.common.prop.password=Пароль +ac.gui.common.prop.bandwidth=Пропускная способность +ac.gui.common.prop.ssid=SSID +ac.gui.common.prop.gen_speed=Скорость генерации +ac.gui.common.prop.altitude=Высота + +# Skill Tree +ac.skill_tree.dev_successful=Производство успешно. +ac.skill_tree.dev_failed=Производство провалено. +ac.skill_tree.progress=Прогрес... +ac.skill_tree.noenergy=Недостаточно энергии. +ac.skill_tree.condition_fail=Состояние развития не соблюдено. +ac.skill_tree.learn_question=Выучить? (Потребление Estm.:%s ЕСЛИ) +ac.skill_tree.level_question=Продолжить? +ac.skill_tree.req=Нужно. +ac.skill_tree.skill_not_learned=Умение не выучено. +ac.skill_tree.skill_exp=Опыт умения: +ac.skill_tree.uplevel=Улучшить до %s +ac.skill_tree.anyskill=Любое умение выучено до уровня: %d +ac.skill_tree.level_fail=Сначала вам надо получить %d уровень. + +ac.skill_tree.type_portable=Портативный производитель +ac.skill_tree.type_normal=Обычный производитель +ac.skill_tree.type_advanced=Продвинутый производитель + +ac.skill_tree.console.init=Добро пожаловать в Academy OS, Ver 1.0.1\nCopyright (c) Academy Tech. All rights reserved. \nПользователь %s обнаружен, Запуск системы...... +ac.skill_tree.console.invalid_cat=\nFATAL: Категория пользовательских возможностей неверна, запуск отменен.\n +ac.skill_tree.console.learn_hint=Наберите `learn` чтобы приобрести новую категорию.\n +ac.skill_tree.console.override=\nWARNING: Переопределение системы! Обнаруженое наружное вторжение.....\n\nСБРАСЫВАНИЕ СПОСОБНОСТЕЙ: Используйте команду `reset` чтобы сбросить китегорию. \nМинимальный уровень способностей:3, и индукционный фактор должен быть в инвентаре.\n +ac.skill_tree.console.boot_failed=Запуск провелен.\n +ac.skill_tree.console.invalid_command=Неверная команда.\n +ac.skill_tree.console.progress=Прогрес: %s%% +ac.skill_tree.console.reset_begin=Начат сброс категории... +ac.skill_tree.console.reset_succ=Успешный сброс личной реальности.\n +ac.skill_tree.console.reset_fail=Сброс личной реальности провален.\n +ac.skill_tree.console.reset_fail_dev=Неможу сбросить возможности -- Надо использувать продвинутый производитель.\n +ac.skill_tree.console.reset_fail_other=Неможем сбросить способности -- Уровень ниже 3, или индукционный фактор не обнаружен.\n +ac.skill_tree.console.dev_begin=начало симуляции......\n +ac.skill_tree.console.dev_succ=Производство успешно.\n +ac.skill_tree.console.dev_fail=Производство провалено.\n + +# Phase Generator + +# Imag Fusor + +# Metal Former +ac.gui.metal_former.mode.etch=Гравировка +ac.gui.metal_former.mode.plate=Дробление пластин +ac.gui.metal_former.mode.incise=Вырезка +ac.gui.metal_former.mode.refine=Очистка + +# Ability interference block +ac.gui.ability_interf.switch=Переключить +ac.ability_interf.cantuse=Вы не можете использовать этот блок помех. + +# UI Editing +ac.gui.uiedit.elements=Элементы + +ac.gui.uiedit.elm.cpbar=Индикатор CP +ac.gui.uiedit.elm.keyhint=Контроль подсказок +ac.gui.uiedit.elm.notification=Уведомления +ac.gui.uiedit.elm.media=Медиа проигрыватель + +# Cat Engine +ac.cat_engine.unlink=Отключен от ноды meow~ +ac.cat_engine.notfound=Поблизости не найдена нода meow~ +ac.cat_engine.linked=Подключен к ноду подназванием %s meow~ + +# Tutorials +ac.gui.crafttype.shaped=Shaped Crafting +ac.gui.crafttype.shapeless=Shapeless Crafting + +ac.tutorial.crafting=Crafting: %s +ac.tutorial.misaka=Misaka Не.%d +ac.tutorial.update=Cloud Terminal обновлен + +# Heads Or Tails +ac.headsOrTails.0=Результат ХВОСТЫ! +ac.headsOrTails.1=Результат ГОЛОВЫ! + +# Converter Block +ac.converter.desc_template=Конвертирует %s в %s +ac.skill_tree.dev_developing=Производим... + +# About App +ac.about.donators_info=In no particular order\nThe list will be updated once a version diff --git a/src/main/resources/assets/academy/lang/zh_cn.lang b/src/main/resources/assets/academy/lang/zh_cn.lang index ca8cd8f54..7895f7af6 100644 --- a/src/main/resources/assets/academy/lang/zh_cn.lang +++ b/src/main/resources/assets/academy/lang/zh_cn.lang @@ -496,4 +496,4 @@ ac.headsOrTails.1=硬币反面朝上 ac.converter.desc_template=转换%s到%s # About App -ac.about.donators_info=排名不分先后\n名单每个版本更新一次 \ No newline at end of file +ac.about.donators_info=排名不分先后 \ No newline at end of file diff --git a/src/main/resources/assets/academy/lang/zh_tw.lang b/src/main/resources/assets/academy/lang/zh_tw.lang index 487488698..8a34c3f61 100644 --- a/src/main/resources/assets/academy/lang/zh_tw.lang +++ b/src/main/resources/assets/academy/lang/zh_tw.lang @@ -496,4 +496,4 @@ ac.converter.desc_template=轉換%s到%s # About App ac.app.about.name=關於 -ac.about.donators_info=排名不分先後\n名單每個版本更新壹次 +ac.about.donators_info=排名不分先後 diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 5a67caa76..602960550 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -4,7 +4,7 @@ "name": "Academy Craft", "description": "A mod about superability. Become an ESPer and alter your reality in Minecraft!", "version": "${version}", - "url": "http://ac.li-dev.cn/", + "url": "https://ac.li-dev.cn/", "updateUrl": "", "authorList": ["Lambda Innovation"], "credits": "All the players of the mod, like you", diff --git a/src/main/scala/cn/academy/ability/vanilla/vecmanip/skill/StormWing.scala b/src/main/scala/cn/academy/ability/vanilla/vecmanip/skill/StormWing.scala index 09cd84613..3f465c15a 100644 --- a/src/main/scala/cn/academy/ability/vanilla/vecmanip/skill/StormWing.scala +++ b/src/main/scala/cn/academy/ability/vanilla/vecmanip/skill/StormWing.scala @@ -225,10 +225,11 @@ class StormWingContext(p: EntityPlayer) extends Context(p, StormWing) { }) } - defkey(1, Keyboard.KEY_W, () => worldSpace(0, 0, 1)) - defkey(2, Keyboard.KEY_S, () => worldSpace(0, 0, -1)) - defkey(3, Keyboard.KEY_A, () => worldSpace(1, 0, 0)) - defkey(4, Keyboard.KEY_D, () => worldSpace(-1, 0, 0)) + val settings = Minecraft.getMinecraft.gameSettings + defkey(1, settings.keyBindForward.getKeyCode, () => worldSpace(0, 0, 1)) + defkey(2, settings.keyBindBack.getKeyCode, () => worldSpace(0, 0, -1)) + defkey(3, settings.keyBindLeft.getKeyCode, () => worldSpace(1, 0, 0)) + defkey(4, settings.keyBindRight.getKeyCode, () => worldSpace(-1, 0, 0)) } @SideOnly(Side.CLIENT) diff --git a/src/main/scala/cn/academy/ability/vanilla/vecmanip/skill/VecReflection.scala b/src/main/scala/cn/academy/ability/vanilla/vecmanip/skill/VecReflection.scala index 1f6c8c906..dfc6192f1 100644 --- a/src/main/scala/cn/academy/ability/vanilla/vecmanip/skill/VecReflection.scala +++ b/src/main/scala/cn/academy/ability/vanilla/vecmanip/skill/VecReflection.scala @@ -29,7 +29,7 @@ object VecReflection extends Skill("vec_reflection", 4) { MinecraftForge.EVENT_BUS.register(this) @SideOnly(Side.CLIENT) - override def activate(rt: ClientRuntime, keyid: Int) = { + override def activate(rt: ClientRuntime, keyid: Int): Unit = { rt.addKey(keyid, KeyDelegates.contextActivate(this, new VecReflectionContext(_))) } @@ -63,19 +63,19 @@ class VecReflectionContext(p: EntityPlayer) extends Context(p, VecReflection) { import scala.collection.JavaConversions._ @Listener(channel=MSG_MADEALIVE, side=Array(Side.SERVER)) - def s_makeAlive() = { + def s_makeAlive(): Unit = { MinecraftForge.EVENT_BUS.register(this) ctx.consume(overloadToKeep, 0) overloadKeep = ctx.cpData.getOverload } @Listener(channel=MSG_TERMINATED, side=Array(Side.SERVER, Side.CLIENT)) - def g_terminate() = { + def g_terminate(): Unit = { MinecraftForge.EVENT_BUS.unregister(this) } @Listener(channel=MSG_TICK, side=Array(Side.SERVER)) - def s_tick() = { + def s_tick(): Unit = { if(ctx.cpData.getOverload < overloadKeep) ctx.cpData.setOverload(overloadKeep) val range = 4 val entities = WorldUtils.getEntities(player, range, new Predicate[Entity] { @@ -111,10 +111,10 @@ class VecReflectionContext(p: EntityPlayer) extends Context(p, VecReflection) { visited ++= entities if(!consumeNormal) - terminate + terminate() } - private def createNewFireball(source : EntityFireball) = { + private def createNewFireball(source : EntityFireball): Boolean = { source.setDead() val shootingEntity = source.shootingEntity @@ -146,13 +146,13 @@ class VecReflectionContext(p: EntityPlayer) extends Context(p, VecReflection) { } @Listener(channel=MSG_TICK, side=Array(Side.CLIENT)) - def c_tick() = { + def c_tick(): Unit = { if(!consumeNormal) - terminate + terminate() } @SubscribeEvent - def onReflect(evt: ReflectEvent) = { + def onReflect(evt: ReflectEvent): Unit = { if (evt.target.equals(player)) { evt.setCanceled(true) @@ -166,7 +166,7 @@ class VecReflectionContext(p: EntityPlayer) extends Context(p, VecReflection) { * to be one more pre testing. */ @SubscribeEvent - def onLivingAttack(evt: LivingAttackEvent) = { + def onLivingAttack(evt: LivingAttackEvent): Unit = { if (evt.getEntityLiving.equals(player)) { val (performed, _) = handleAttack(evt.getSource, evt.getAmount, passby = true) if (performed) { @@ -177,7 +177,7 @@ class VecReflectionContext(p: EntityPlayer) extends Context(p, VecReflection) { } @SubscribeEvent - def onLivingHurt(evt: LivingHurtEvent) = { + def onLivingHurt(evt: LivingHurtEvent): Unit = { if (evt.getEntityLiving.equals(player) && evt.getAmount <=9999) { val (_, dmg) = handleAttack(evt.getSource, evt.getAmount, passby = false) evt.setAmount(dmg) @@ -187,6 +187,12 @@ class VecReflectionContext(p: EntityPlayer) extends Context(p, VecReflection) { } } + // Sometimes reflection will cause reentrant, e.g. when Guardian + // gives thorns damage to any of its attacks, or + // two players vector-reflect against each other. + // Under these situation, we don't allow recursion of reflection. + private var _isAttacking = false + /** * @param passby If passby=true, and this isn't a complete absorb, the action will not perform. Else it will. * @return (Whether action had been really performed, processed damage) @@ -194,17 +200,23 @@ class VecReflectionContext(p: EntityPlayer) extends Context(p, VecReflection) { private def handleAttack(dmgSource: DamageSource, dmg: Float, passby: Boolean): (Boolean, Float) = { val reflectDamage = lerpf(0.6f, 1.2f, ctx.getSkillExp) * dmg if (!passby) { // Perform the action. - consumeDamage(dmg) - ctx.addSkillExp(dmg * 0.0004f) + _isAttacking = true + + if (!_isAttacking) { + consumeDamage(dmg) + ctx.addSkillExp(dmg * 0.0004f) - val sourceEntity = dmgSource.getImmediateSource - if (sourceEntity != null && sourceEntity != player) { - ctx.attack(sourceEntity, reflectDamage) + val sourceEntity = dmgSource.getImmediateSource + if (sourceEntity != null && sourceEntity != player) { + ctx.attack(sourceEntity, reflectDamage) - if (!SideUtils.isClient) - sendToClient(MSG_EFFECT, sourceEntity.getPositionVector) + if (!SideUtils.isClient) + sendToClient(MSG_EFFECT, sourceEntity.getPositionVector) + } } + _isAttacking = false + (true, dmg - reflectDamage) } else { (reflectDamage>=1, dmg - reflectDamage) @@ -215,9 +227,9 @@ class VecReflectionContext(p: EntityPlayer) extends Context(p, VecReflection) { ctx.consume(0, difficulty * lerpf(300, 160, ctx.getSkillExp)) } - private def consumeDamage(damage: Float) = ctx.consumeWithForce(0, lerpf(20, 15, ctx.getSkillExp) * damage) + private def consumeDamage(damage: Float): Unit = ctx.consumeWithForce(0, lerpf(20, 15, ctx.getSkillExp) * damage) - private def consumeNormal():(Boolean) = { + private def consumeNormal(): Boolean = { ctx.consume(0, lerpf(15, 11, ctx.getSkillExp)) } @@ -234,26 +246,26 @@ class VecReflectionContextC(par: VecReflectionContext) extends ClientContext(par private val ui = new WaveEffectUI(0.4f, 110, 1.6f) @Listener(channel=MSG_MADEALIVE, side=Array(Side.CLIENT)) - private def l_alive() = if (isLocal) { + private def l_alive(): Unit = if (isLocal) { activateHandler = ActivateHandlers.terminatesContext(par) ClientRuntime.instance.addActivateHandler(activateHandler) MinecraftForge.EVENT_BUS.register(this) } @Listener(channel=MSG_TERMINATED, side=Array(Side.CLIENT)) - private def l_terminate() = if (isLocal) { + private def l_terminate(): Unit = if (isLocal) { ClientRuntime.instance.removeActiveHandler(activateHandler) MinecraftForge.EVENT_BUS.unregister(this) } @Listener(channel=MSG_REFLECT_ENTITY, side=Array(Side.CLIENT)) - private def c_reflectEntity(ent: Entity) = { + private def c_reflectEntity(ent: Entity): Unit = { reflect(ent, player) reflectEffect(entityHeadPos(ent)) } @Listener(channel=MSG_EFFECT, side=Array(Side.CLIENT)) - private def reflectEffect(point: Vec3d) = { + private def reflectEffect(point: Vec3d): Unit = { val eff = new WaveEffect(world, 2, 1.1) eff.setPosition(point.x, point.y, point.z) eff.rotationYaw = player.rotationYawHead @@ -264,12 +276,12 @@ class VecReflectionContextC(par: VecReflectionContext) extends ClientContext(par playSound(point) } - private def playSound(pos: net.minecraft.util.math.Vec3d) = { + private def playSound(pos: net.minecraft.util.math.Vec3d): Unit = { ACSounds.playClient(world, pos.x, pos.y, pos.z, "vecmanip.vec_reflection", SoundCategory.AMBIENT, 0.5f, 1.0f) } @SubscribeEvent - def onRenderOverlay(evt: RenderGameOverlayEvent) = { + def onRenderOverlay(evt: RenderGameOverlayEvent): Unit = { if (evt.getType == ElementType.CROSSHAIRS) { val r = evt.getResolution ui.onFrame(r.getScaledWidth, r.getScaledHeight) diff --git a/src/test/java/DonatorListTest.kt b/src/test/java/DonatorListTest.kt new file mode 100644 index 000000000..6ff1338f2 --- /dev/null +++ b/src/test/java/DonatorListTest.kt @@ -0,0 +1,12 @@ +import java.net.URL + +// Tests donation interface. +fun main(args: Array) { + val url = "https://ac.li-dev.cn/analytics" + val con = URL(url).openConnection() + con.doInput = true + + val wr = con.getInputStream() + val text = wr.bufferedReader().readText() + println(text) +} \ No newline at end of file