From 42f03643191bbbb3de377e1a559ae3a18e57131b Mon Sep 17 00:00:00 2001 From: Sharlotte <60801210+sharlotte-mobile@users.noreply.github.com> Date: Sat, 5 Dec 2020 20:10:03 +0900 Subject: [PATCH 01/13] ko hotfix translate all missing values removed over-translated values and do Uniform some terms, correction of typos. --- core/assets/bundles/bundle_ko.properties | 124 ++++++++++++----------- 1 file changed, 64 insertions(+), 60 deletions(-) diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 4dd94eb923..d61769d770 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1,5 +1,5 @@ credits.text = 만든이: [royal]Anuken[] - [sky]anukendev@gmail.com[] -credits = 제작자 +credits = 제작진 contributors = 번역가와 기여자 discord = Mindustry Discord 서버에 가입하세요! link.discord.description = Mindustry Discord 공식 대화방 @@ -15,7 +15,7 @@ link.wiki.description = 공식 Mindustry 위키 link.suggestions.description = 새 기능 제안하기 linkfail = 링크를 열지 못했습니다!\nURL이 클립보드에 복사되었습니다. screenshot = 스크린 캡처가 {0} 에 저장되었습니다. -screenshot.invalid = 맵이 너무 커서 스크린 캡처에 사용될 메모리가 부족할 수 있습니다. +screenshot.invalid = 맵이 너무 커서 스크린 캡처에 사용될 메모리가 부족합니다. gameover = 게임 오버 gameover.disconnect = 연결 끊김 gameover.pvp = [accent]{0}[] 팀이 승리했습니다! @@ -75,7 +75,7 @@ level.highscore = 최고 점수: [accent]{0} level.select = 맵 선택 level.mode = 게임 모드: coreattack = < 코어가 공격을 받고 있습니다! > -nearpoint = [[ [scarlet]즉시 적 소환구역에서 떠나세요[] ]\n인근 건물들과 유닛들은 초토화됩니다! +nearpoint = [[ [scarlet]즉시 적 소환구역에서 떠나십시오[] ]\n단계가 시작하는 순간 인근 건물들과 유닛들이 전멸됩니다! database = 코어 데이터베이스 savegame = 게임 저장 loadgame = 게임 불러오기 @@ -149,7 +149,7 @@ unlocked = 새로운 콘텐츠가 해금되었습니다! available = 새로운 콘텐츠 해금이 가능합니다! completed = [accent]완료됨 techtree = 연구 기록 -research.legacy = [accent]5.0[] 연구 데이터를 찾았습니다.\n[accent]이 데이터를 불러오시겠습니까?[], 아니면 이 데이터를 무시하고 캠페인을 새로 시작하시겠습니까? [accent]무시한 데이터는 삭제됩니다.[] (권장됨)? +research.legacy = [accent]5.0[] 연구 데이터를 찾았습니다.\n[accent]이 데이터를 불러오시겠습니까?[], 아니면 이 데이터를 무시하고 캠페인을 새로 시작하시겠습니까? [accent]무시한 데이터는 삭제됩니다.[] (권장됨) research.load = 불러오기 research.discard = 무시하기 research.list = [lightgray]연구: @@ -167,7 +167,7 @@ server.kicked.serverClose = 서버 닫힘. server.kicked.vote = 당신은 투표로 추방되었습니다. 안녕히 가세요! server.kicked.clientOutdated = 구버전 클라이언트입니다! 게임을 업데이트하세요! server.kicked.serverOutdated = 구버전 서버입니다! 호스트에게 업데이트를 요청하세요! -server.kicked.banned = 당신은 이 서버에서 차단되었습니다. +server.kicked.banned = 당신은 이 서버에서 영구적으로 차단되었습니다. server.kicked.typeMismatch = 이 서버는 현재 빌드 유형과 호환되지 않습니다. server.kicked.playerLimit = 서버의 인원이 꽉 찼습니다. 빈 슬롯이 생길 때까지 기다려주세요. server.kicked.recentKick = 최근에 추방되었습니다.\n추방 쿨타임이 끝날 때까지 기다리세요. @@ -196,6 +196,7 @@ servers.local = 로컬 서버 servers.remote = 원격 서버 servers.global = 커뮤니티 서버 +servers.disclaimer = 커뮤니티 서버는 개발자가 소유하거나 제어하지 [accent]않습니다[].\n\n서버들은 전연령대에 적합하지 않은 사용자 지정 콘텐츠를 보유할 수도 있습니다. servers.showhidden = 서버 숨기기 / 보이기 server.shown = 서버 숨기기 server.hidden = 서버 보이기 @@ -222,8 +223,8 @@ confirmban = 정말로 "{0}[white]" 을(를) 차단하시겠습니까? confirmkick = 정말로 "{0}[white]" 을(를) 추방하시겠습니까? confirmvotekick = 정말로 "{0}[white]" 을(를) 투표로 추방하시겠습니까? confirmunban = 정말로 이 플레이어를 차단 해제하시겠습니까? -confirmadmin = 정말로 "{0}[white]" 을(를) 관리자로 만들겠습니까? -confirmunadmin = 정말로 "{0}[white]"의 관리자 상태를 제거하시겠습니까? +confirmadmin = 정말로 "{0}[white]" 을(를) 관리자로 임명하겠습니까? +confirmunadmin = 정말로 "{0}[white]"의 관리자를 박탈하시겠습니까? joingame.title = 게임 참가 joingame.ip = 주소: disconnect = 연결이 끊어졌습니다. @@ -293,11 +294,11 @@ quit.confirm.tutorial = 튜토리얼을 종료하시겠습니까?\n튜토리얼 loading = [accent]불러오는중... reloading = [accent]모드 새로고침하는중... saving = [accent]저장중... -respawn = [accent][[{0}][] 키를 눌러 코어에서 부활 -cancelbuilding = [accent][[{0}][] 를 눌러 계획 초기화 -selectschematic = [accent][[{0}][] 를 눌러 선택+복사 -pausebuilding = [accent][[{0}][] 를 눌러 건설 일시중지 -resumebuilding = [scarlet][[{0}][] 를 눌러 건설 재개 +respawn = [accent][[{0}][] 키를 눌러 코어에서 부활하세요. +cancelbuilding = [accent][[{0}][] 를 눌러 건설 계획을 초기화하세요. +selectschematic = [accent][[{0}][] 를 눌러 선택+복사하세요. +pausebuilding = [accent][[{0}][] 를 눌러 건설을 일시중지하세요. +resumebuilding = [scarlet][[{0}][] 를 눌러 건설을 재개하세요. showui = UI를 .\n[accent][[{0}][] 키를 눌러 UI를 활성화하세요. wave = [accent]{0} 단계 wave.cap = [accent]단계 {0}/{1} @@ -386,7 +387,7 @@ editor.errorimage = 이것은 맵이 아니라 사진입니다.\n\n3.5/build 40 editor.errorlegacy = 이 맵은 너무 오래되어 더 이상 지원되지 않는 구형 맵 형식을 사용합니다. editor.errornot = 맵 파일이 아닙니다. editor.errorheader = 이 맵 파일은 유효하지 않거나 손상되었습니다. -editor.errorname = 맵에 이름이 지정되어 있지 않습니다. 저장 파일을 불러오려 합니까? +editor.errorname = 맵에 이름이 지정되어 있지 않습니다. 저장 파일을 불러오려고 시도하는 건가요? editor.update = 업데이트 editor.randomize = 무작위 editor.apply = 적용 @@ -427,7 +428,7 @@ toolmode.replaceall.description = 맵에 있는 모든 블록을 재배치합니 toolmode.orthogonal = 직각 toolmode.orthogonal.description = 직각으로 블록을 배치합니다. toolmode.square = 정사각형 -toolmode.square.description = 정사각형 형태의 브러시. +toolmode.square.description = 정사각형 형태의 브러시로 교체합니다. toolmode.eraseores = 자원 초기화 toolmode.eraseores.description = 자원만 초기화합니다. toolmode.fillteams = 팀 채우기 @@ -486,7 +487,7 @@ memory2 = Mem:\n {0}mb +\n {1}mb language.restart = 언어 설정을 적용하려면 게임을 다시 시작하세요. settings = 설정 tutorial = 튜토리얼 -tutorial.retake = 튜토리얼 다시 시작 +tutorial.retake = 튜토리얼을 다시 시작하기 editor = 편집기 mapeditor = 맵 편집기 @@ -500,8 +501,8 @@ requirement.research = {0} 연구 requirement.capture = {0} 점령 bestwave = [lightgray]최고 단계: {0} launch.text = 출격 -research.multiplayer = 캠페인 멀티 플레이 시에는 해당 캠페인 서버의 주최자만 연구할 수 있습니다. -map.multiplayer = 캠페인 멀티 플레이 시에는 해당 캠페인 서버의 주최자만 다른 섹터들을 보고, 이동이 가능합니다. +research.multiplayer = 캠페인 멀티 플레이 시에는 해당 캠페인 서버의 호스트만 연구할 수 있습니다. +map.multiplayer = 캠페인 멀티 플레이 시에는 해당 캠페인 서버의 호스트만 다른 섹터들을 보고, 이동이 가능합니다. uncover = 지역 개방 configure = 초기자원 설정 @@ -518,7 +519,7 @@ boss.health = 수호자 체력 connectfail = [scarlet]연결 오류:\n\n[accent]{0} error.unreachable = 서버에 연결하지 못했습니다.\n서버 주소가 정확히 입력되었나요? error.invalidaddress = 잘못된 주소입니다. -error.timedout = 시간 초과!\n서버에 포트 포워딩이 설정되어 있고 주소가 올바른지 확인하십시오. +error.timedout = 시간 초과!\n서버에 포트 포워딩이 설정되어 있고 주소가 올바른지 확인하세요. error.mismatch = 패킷 오류\n클라이언트/서버 버전이 일치하지 않습니다.\n접속하려는 서버가 최신 버전인지 확인하세요! error.alreadyconnected = 이미 접속 중입니다. error.mapnotfound = 맵 파일을 찾을 수 없습니다! @@ -535,7 +536,7 @@ weather.fog.name = 안개 sectors.unexplored = [lightgray]미개척지 sectors.resources = 자원: sectors.production = 분당 자원 생산량: -sectors.export = Export: +sectors.export = 분당 자원 수출량: sectors.time = 지역 진행 시간: sectors.threat = 지역 위험도: sectors.wave = 진행 중 단계: @@ -546,7 +547,7 @@ sectors.select = 선택 sectors.nonelaunch = [lightgray]없음 (sun) sectors.rename = 구역 이름 변경 sectors.enemybase = [scarlet]적 기지 -sectors.vulnerable = [scarlet]]취약 +sectors.vulnerable = [scarlet]취약 sectors.underattack = [scarlet]공격받고 있습니다! [accent]{0}% 손상됨. sectors.survives = [accent]{0} 단계 이상 버티세요. sectors.go = 지역 진입 @@ -566,14 +567,14 @@ threat.eradication = 극한 planets = 태양계 -planet.serpulo.name = 세르풀로 +planet.serpulo.name = 세르플로 planet.sun.name = 태양 sector.impact0078.name = 폐허 : Impact 0078 sector.groundZero.name = Zero 전초기지 sector.craters.name = 크레이터 sector.frozenForest.name = 얼어붙은 숲 -sector.ruinousShores.name = 폐허 : 해안가 +sector.ruinousShores.name = 파괴된 해안가 sector.stainedMountains.name = 얼룩진 산맥 sector.desolateRift.name = 황폐한 협곡 sector.nuclearComplex.name = 핵 생산 단지 @@ -606,15 +607,15 @@ sector.planetaryTerminal.description = 이 행성에서의 마지막 전투를 settings.language = 언어 settings.data = 게임 데이터 settings.reset = 설정 초기화 -settings.rebind = 키 설정 -settings.resetKey = 키 초기화 +settings.rebind = 조작키 설정 +settings.resetKey = 조작키 설정 초기화 settings.controls = 조작 settings.game = 게임 settings.sound = 소리 settings.graphics = 그래픽 settings.cleardata = 게임 데이터 초기화 settings.clear.confirm = 정말로 이 데이터를 지우시겠습니까?\n되돌릴 수 없습니다! -settings.clearall.confirm = [scarlet]경고![]\n이 작업은 저장된 맵, 맵파일, 잠금 해제된 목록과 키 매핑, 그리고 모든 데이터를 삭제합니다.\n확인 버튼을 다시 눌러 모든 데이터를 삭제하고 게임에서 나갑니다. +settings.clearall.confirm = [scarlet]경고![]\n이 작업은 저장된 맵, 맵파일, 잠금 해제된 목록과 조작키 설정, 그리고 모든 데이터를 삭제합니다.\n확인 버튼을 다시 눌러 모든 데이터를 삭제하고 게임에서 나갑니다. settings.clearsaves.confirm = 정말로 모든 저장된 파일들을 삭제하시겠습니까? settings.clearsaves = 저장 초기화 settings.clearresearch = 연구 초기화 @@ -628,7 +629,7 @@ yes = O no = X info.title = 정보 error.title = [scarlet]오류가 발생했습니다. -error.crashtitle = 오류가 발생했습니다 +error.crashtitle = 오류가 발생했습니다. unit.nobuild = [scarlet]건설 불가 lastaccessed = [lightgray]마지막 조작: {0} block.unknown = [lightgray]??? @@ -698,9 +699,9 @@ stat.abilities = 능력 stat.canboost = 부스터 stat.flying = 비행 -ability.forcefield = 수호 역장 -ability.repairfield = 수리 파동 -ability.statusfield = 강화 오오라 +ability.forcefield = 보호막 필드 +ability.repairfield = 수리 필드 +ability.statusfield = 상태이상 필드 ability.unitspawn = {0} 공장 ability.shieldregenfield = 방어막 복구 필드 ability.movelightning = 가속 전격 @@ -837,7 +838,7 @@ uiscale.reset = UI 스케일이 변경되었습니다.\n"확인"버튼을 눌러 uiscale.cancel = 취소 후 나가기 setting.bloom.name = 화려한 효과 keybind.title = 조작키 설정 -keybinds.mobile = [scarlet]대부분의 키 맵핑은 모바일에서 작동하지 않습니다. 기본 이동만 지원됩니다. +keybinds.mobile = [scarlet]대부분의 조작키 설정은 모바일에서 작동하지 않습니다. 기본 이동만 지원됩니다. category.general.name = 일반 category.view.name = 보기 category.multiplayer.name = 멀티플레이어 @@ -992,8 +993,8 @@ unit.quasar.name = 퀘이사 unit.crawler.name = 크롤러 unit.atrax.name = 아트락스 unit.spiroct.name = 스피록트 -unit.arkyid.name = 알카이드 -unit.toxopid.name = 톡소오피드 +unit.arkyid.name = 아키드 +unit.toxopid.name = 톡소피드 unit.flare.name = 플레어 unit.horizon.name = 호라이즌 unit.zenith.name = 제니스 @@ -1005,7 +1006,7 @@ unit.mega.name = 메가 unit.quad.name = 쿼드 unit.oct.name = 옥트 unit.risso.name = 리소 -unit.minke.name = 민키 +unit.minke.name = 민케 unit.bryde.name = 브라이드 unit.sei.name = 세이 unit.omura.name = 오무라 @@ -1013,9 +1014,9 @@ unit.alpha.name = 알파 unit.beta.name = 베타 unit.gamma.name = 감마 unit.scepter.name = 셉터 -unit.reign.name = 린 +unit.reign.name = 레인 unit.vela.name = 벨라 -unit.corvus.name = 코르부스 +unit.corvus.name = 코르버스 block.resupply-point.name = 보급 지점 block.parallax.name = 패럴랙스 @@ -1058,7 +1059,7 @@ block.deepwater.name = 깊은 물 block.water.name = 물 block.tainted-water.name = 오염된 물 block.darksand-tainted-water.name = 오염된 젖은 검은 모래 -block.tar.name = 석유 +block.tar.name = 타르 block.stone.name = 바위 block.sand.name = 모래 block.darksand.name = 검은 모래 @@ -1198,7 +1199,7 @@ block.cyclone.name = 사이클론 block.fuse.name = 퓨즈 block.shock-mine.name = 전격 지뢰 block.overdrive-projector.name = 과부하 프로젝터 -block.force-projector.name = 포스 프로젝터 +block.force-projector.name = 보호막 프로젝터 block.arc.name = 아크 block.rtg-generator.name = RTG 발전기 block.spectre.name = 스펙터 @@ -1257,7 +1258,7 @@ hint.placeDrill = 드릴을 설치하려면 오른쪽 아래의 \ue85e [accent] hint.placeDrill.mobile = 오른쪽 아래 메뉴의 \ue85e [accent]드릴[]을 선택하고, \uf870 [accent]드릴[] 를 선택해서 구리 광석 위를 누르십시오.\n\n설치를 완료하려면 오른쪽 아래의 \ue800 [accent]완료 버튼[]을 누르십시오. hint.placeConveyor = 컨베이어는 아이템을 드릴에서 다른 블록으로 이동시켜줍니다. \ue814 [accent]분배[] 카테고리에서 \uf896 [accent]컨베이어[]를 선택하십시오.\n\n클릭하거나 드래그로 다수의 컨베이어를 설치할 수 있습니다.\n클릭하고 놓지 않은채로 마우스 [accent]휠을 돌리면 돌아갑니다. hint.placeConveyor.mobile = 컨베이어는 아이템을 드릴에서 다른 블록으로 이동시켜줍니다. \ue814 [accent]분배[] 카테고리에서 \uf896 [accent]컨베이어[]를 선택하십시오.\n\n여러개의 컨베이어를 놓으려면 손가락으로 누른채로 끌어서 설치 범위를 지정하십시오. -hint.placeTurret = 적에게서 당신의 기지를 막아내려면 \uf861 [accent]포탑[]를 설치하십시오.\n\n포탑 탄약 필요 - 지금은 \uf838구리가 필요합니다.\n컨베이어를 사용해 드릴에 구리를 공급하십시오. +hint.placeTurret = 적에게서 당신의 기지를 막아내려면 \uf861 [accent]포탑[]를 설치하십시오.\n\n포탑 탄약 필요 - 지금은 \uf838 구리가 필요합니다.\n컨베이어를 사용해 드릴에 구리를 공급하십시오. hint.breaking = 블록을 부수려면 [accent]오른클릭[]이나 드래그를 하십시오. hint.breaking.mobile = 블럭을 부수려면 오른쪽 아래의 \ue817 [accent]망치[]를 눌러 해체 모드를 활성화 하십시오.\n\n손가락으로 누른채로 끌어서 해체 범위를 지정하십시오. hint.research = 새 기술을 연구하려면 \ue875 [accent]연구[]버튼을 누르십시오. @@ -1279,9 +1280,12 @@ hint.payloadDrop.mobile = 다시 내려놓으려면 빈 공간에서 [accent]화 hint.waveFire = [accent]Wave[]포탑에 탄약으로 물을 넣으면 주변의 불을 자동으로 꺼줍니다. hint.generator = \uf879 [accent]화력 발전기[]는 석탄을 태워서 주변 블록에 전력을 전달합니다.\n\n \uf87f 더 넓은 범위의 블록에 전력을 전달하려면 [accent]Power Nodes[]를 사용하십시오. hint.guardian = [accent]수호자[] 유닛들은 방어력을 가집니다. [accent]구리[]와 [accent]납[]같은 약한 탄약으로는 [scarlet]아무런 효과도 없습니다[].\n\n그런 수호자를 없애려면 높은 단계의 포탑 또는 \uf835 [accent]흑연[]을 탄약으로 넣은 \uf861듀오/\uf859살보를 사용하십시오. +hint.coreUpgrade = 코어는 [accent]상위 코어를 위에 설치함[]으로써 업그레이드될 수 있습니다.\n\n [accent]기반[] 코어를  [accent]조각[] 코어 위에 설치하십시오. 주변에 장애물이 없는지도 확인하십시오. +hint.presetLaunch = [accent]얼어붙은 숲[]과 같은 회색[accent]캠페인 지역[]은 어디에서나 출격해서 올 수 있습니다. 주변 지역을 점령하지 않아도 됩니다.\n\n이와 같은 [accent]네임드 지역[]들은 [accent]선택적[]입니다. +hint.coreIncinerate = 코어가 아이템으로 가득 찬 후에 받는 모든 아이템들은 [accent]소각[]될 것입니다. item.copper.description = 가장 기본적인 건설 재료. 모든 유형의 블록에서 광범위하게 사용됩니다. -item.copper.details = 평범한 구리. 세르풀로에 비정상적으로 많이 분포되어 있습니다. 별다른 보강재 없이는 구조적 문제 때문에 내구성이 비교적 약합니다. +item.copper.details = 평범한 구리. 세르플로에 비정상적으로 많이 분포되어 있습니다. 별다른 보강재 없이는 구조적 문제 때문에 내구성이 비교적 약합니다. item.lead.description = 기본 초반 재료. 전자 및 액체 수송 블록에서 광범위하게 사용되는 자원입니다. item.lead.details = 밀도가 높으며 반응성이 적은 자원. 배터리에 주로 사용됩니다. item.metaglass.description = 초강력 방탄유리. 액체 분배 및 저장에 광범위하게 사용됩니다. @@ -1398,7 +1402,7 @@ block.laser-drill.description = 레이저 기술을 통해 더욱 빠르게 채 block.blast-drill.description = 최상위 드릴. 많은 양의 전력이 필요합니다. block.water-extractor.description = 지하수를 추출합니다. 물을 구하기 어려운 곳에서 사용합니다. block.cultivator.description = 대기 중의 작은 농도의 포자를 산업용 포자로 배양합니다. -block.cultivator.details = 재발견된 기술. 가장 효율적으로 대량의 유기체를 생산할 때 사용된다. 과거, 세르플을 뒤덮은 포자의 최초 배양지로 판단된다. +block.cultivator.details = 재발견된 기술. 가장 효율적으로 대량의 유기체를 생산할 때 사용된다. 과거, 세르플로을 뒤덮은 포자의 최초 배양지로 판단된다. block.oil-extractor.description = 석유를 추출하기 위해 많은 양의 전력과 모래 및 물을 사용합니다. block.core-shard.description = 기지의 핵심입니다. 파괴되면 해당 지역과의 모든 연결이 끊어집니다. 이런 일이 일어나지 않도록 하십시오. block.core-shard.details = 첫 번째 버전. 휴대용. 자가복제 가능. 일회용 출격 추진기를 가졌으며, 행성간 이동에는 부적합함. @@ -1410,23 +1414,23 @@ block.vault.description = 각 유형의 많은 양의 자원을 저장합니다. block.container.description = 각 유형의 자원을 소량 저장합니다. 언로더 블록을 사용하여 컨테이너에서 자원을 빼낼 수 있습니다. block.unloader.description = 근처의 비 수송 블록에서 자원을 빼냅니다. 눌러서 빼낼 자원을 변경할 수 있십니다. block.launch-pad.description = 코어 출격 없이도 자원을 묶어 출격시킬 수 있습니다. -block.duo.description = 작고 저렴한 포탑. 지상 유닛에 유용합니다. -block.scatter.description = 저렴한 대공 포탑. 적군에게 납덩어리, 고철, 또는 강화 유리 조각 덩어리를 뿌립니다. -block.scorch.description = 주변의 모든 적을 불태웁니다. 근거리에서 매우 효과적입니다. -block.hail.description = 작은 장거리 포병 포탑입니다. -block.wave.description = 중형 포탑. 적에게 액체를 발사합니다. 물이 공급되면 자동으로 화재를 진압합니다. -block.lancer.description = 중형 대지 레이저 포탑. 강력한 에너지 빔을 충전하여 발사합니다. -block.arc.description = 작은 근거리 전격 포탑. 적에게 전격 아크를 발사합니다. -block.swarmer.description = 중형 미사일 포탑. 공중과 지상의 적을 모두 공격하며, 유도탄을 발사합니다. -block.salvo.description = 더 큰 고급 듀오 포탑입니다. 적에게 총알을 빠르게 발사합니다. -block.fuse.description = 넓은 근거리 파편 포탑. 근처의 적에게 3개의 관통 총알을 발사합니다. -block.ripple.description = 매우 강력한 포병 포탑. 원거리에 있는 적에게 포탄 무리를 쏘세요. -block.cyclone.description = 대공 및 대지 포탑. 근처 적에게 폭발탄을 발사합니다. -block.spectre.description = 거대한 이중 배럴 대포. 공중 및 지상 목표물에 큰 관통 철갑탄을 발사합니다. -block.meltdown.description = 거대한 레이저 대포. 근처의 적에게 지속적인 레이저 빔을 충전하여 발사합니다. 냉각수가 있어야 작동합니다. -block.foreshadow.description = 긴 거리에 걸친 거대한 단일 목표 볼트를 발사합니다. -block.repair-point.description = 주변에서 가장 가까운 유닛을 지속적으로 치료합니다. -block.segment.description = 날아오는 발사체를 요격합니다. 레이저는 목표 대상이 아닙니다. +block.duo.description = 적에게 탄환을 교대하며 발사합니다. +block.scatter.description = 적군에게 납, 고철, 또는 강화 유리 조각 덩어리를 발사합니다. +block.scorch.description = 주변의 모든 지상 적을 불태웁니다. 근거리에서 매우 효과적입니다. +block.hail.description = 장거리에 걸쳐 지상 적에게 작은 포탄을 발사합니다. +block.wave.description = 적에게 액체 줄기를 발사합니다. 물이 공급되면 자동으로 화재를 진압합니다. +block.lancer.description = 지상 목표물에게 강력한 에너지 빔을 충전하여 발사합니다. +block.arc.description = 지상 목표물에게 전격 아크를 발사합니다. +block.swarmer.description = 적에게 유도탄을 발사합니다. +block.salvo.description = 적에게 총알을 빠르게 일제히 발사합니다. +block.fuse.description = 주변 적에게 3개의 단거리 관통 레이저를 발사합니다. +block.ripple.description = 장거리에 걸쳐 지상 적에게 포탄 무리를 발사합니다. +block.cyclone.description = 근처 적에게 폭발 파편 덩어리를 발사합니다. +block.spectre.description = 공중 및 지상 목표물에게 큰 관통 철갑탄을 발사합니다. +block.meltdown.description = 주변 적에게 지속적인 레이저 빔을 충전하여 발사합니다. 냉각 액체가 있어야 작동합니다. +block.foreshadow.description = 장거리에 걸친 거대한 단일 목표 저격탄을 발사합니다. +block.repair-point.description = 인근에 가장 가까운 유닛을 지속적으로 치료합니다. +block.segment.description = 날아오는 발사체를 요격합니다. 큰 발사체에겐 조준되지 않습니다. block.parallax.description = 공중 목표물을 끌어오는 견인 광선을 발사하며, 견인 과정에서 데미지를 줍니다. block.tsunami.description = 적에게 강력한 액체 줄기를 발사합니다. 물이 공급되면 자동으로 주변의 화재를 진압합니다. block.silicon-crucible.description = 추가적으로 파이라타이트를 사용하여 더 높은 온도에서 석탄과 모래를 제련합니다. 뜨거운 곳에서 더 효율적입니다. @@ -1452,7 +1456,7 @@ block.logic-display.description = 프로세서를 이용해 그래픽을 출력 block.large-logic-display.description = 프로세서를 이용해 그래픽을 출력할 수 있습니다. block.interplanetary-accelerator.description = 거대한 전자기 레일건 타워. 코어를 행성 간 이동을 위한 탈출 속도까지 가속합니다. -unit.dagger.description = 주변 모든 적에게 일반적인 탄환을 발사합니다. +unit.dagger.description = 주변 모든 적에게 일반적인 탄환을 발사합니다. unit.mace.description = 주변 모든 적에게 화염 줄기를 발사합니다. unit.fortress.description = 지상 목표물에 장거리 포탄을 발사합니다. unit.scepter.description = 주변 모든 적에게 장전된 탄환을 일제히 발사합니다. @@ -1465,8 +1469,8 @@ unit.corvus.description = 적에게 피해를 주고, 아군 구조물을 수리 unit.crawler.description = 적에게 달려들어서 거대한 폭발을 일으키는 자폭을 합니다. unit.atrax.description = 지상 목표물을 약화하는 광재 구체를 발사합니다. 대부분의 지형 위를 밟을 수 있습니다. unit.spiroct.description = 적에게 흡혈 레이저 빔을 발사하며, 흡혈을 통해 체력을 회복합니다. 대부분의 지형 위를 밟을 수 있습니다. -unit.arkyid.description = 적에게 흡혈 레이저 빔을 발사하며, 흡혈을 통해 체력을 회복합니다. 대부분의 지형 위를 밟을 수 있습니다. -unit.toxopid.description = 적에게 큰 전기 확산탄과 관통 레이저를 발사합니다. 대부분의 지형 위를 밟을 수 있습니다. +unit.arkyid.description = 적에게 큰 흡혈 레이저 빔을 발사하며, 흡혈을 통해 체력을 회복합니다. 대부분의 지형 위를 밟을 수 있습니다. +unit.toxopid.description = 적에게 큰 전격 포탄 무리와 관통 레이저를 발사합니다. 대부분의 지형 위를 밟을 수 있습니다. unit.flare.description = 지상 목표물에 일반적인 탄환을 발사합니다. unit.horizon.description = 지상 목표물에 폭탄을 투하합니다. unit.zenith.description = 주변 모든 적에게 미사일을 살포합니다. From 8c0477f6bdb76a4e08d0dee26e967fc3ad6a4330 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 10:30:46 -0500 Subject: [PATCH 02/13] Fixed #3795 --- core/src/mindustry/net/ArcNetProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/net/ArcNetProvider.java b/core/src/mindustry/net/ArcNetProvider.java index 91043037e8..da3cf9fb42 100644 --- a/core/src/mindustry/net/ArcNetProvider.java +++ b/core/src/mindustry/net/ArcNetProvider.java @@ -68,7 +68,7 @@ public class ArcNetProvider implements NetProvider{ } }); - server = new Server(8192, 8192, new PacketSerializer()); + server = new Server(32768, 8192, new PacketSerializer()); server.setMulticast(multicastGroup, multicastPort); server.setDiscoveryHandler((address, handler) -> { ByteBuffer buffer = NetworkIO.writeServerData(); From edbced6642f07189566446583bafcd11b9849e65 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 10:58:30 -0500 Subject: [PATCH 03/13] Fixed #3798 --- core/src/mindustry/logic/LStatement.java | 1 + core/src/mindustry/logic/LStatements.java | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/logic/LStatement.java b/core/src/mindustry/logic/LStatement.java index bf8637ac63..ea54bd833b 100644 --- a/core/src/mindustry/logic/LStatement.java +++ b/core/src/mindustry/logic/LStatement.java @@ -114,6 +114,7 @@ public abstract class LStatement{ t.actions(Actions.alpha(0), Actions.fadeIn(0.3f, Interp.fade)); t.top().pane(inner -> { + inner.marginRight(24f); inner.top(); hideCons.get(inner, hide); }).top(); diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java index f7f5d2ea4f..d8fce354ad 100644 --- a/core/src/mindustry/logic/LStatements.java +++ b/core/src/mindustry/logic/LStatements.java @@ -528,7 +528,9 @@ public class LStatements{ stack.clearChildren(); stack.addChild(tables[selected]); - t.pack(); + + t.parent.parent.pack(); + t.parent.parent.invalidateHierarchy(); }).size(80f, 50f).growX().checked(selected == fi).group(group); } t.row(); From d7929560564048459599de429ec53628a521f85c Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 5 Dec 2020 15:46:55 -0300 Subject: [PATCH 04/13] Brazillian servers V6 get in, we are going to Brazil --- servers_v6.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/servers_v6.json b/servers_v6.json index 86d64a9d7c..9e143d98f3 100644 --- a/servers_v6.json +++ b/servers_v6.json @@ -46,5 +46,9 @@ { "name": "Surrealment", "address": ["md.surrealment.com"] + }, + { + "name": "MindustryBR", + "address": ["mindustryptbr.ddns.net", "mindustryptbr.ddns.net:4444", "mindustryptbr.myddns.me:6666", "mindustryptbr.myddns.me:5555"] } ] From 97fa8057baeb0900db54dd866bf8f8cb62beaf12 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 14:16:02 -0500 Subject: [PATCH 05/13] Fixed #3805 --- core/src/mindustry/world/blocks/logic/LogicBlock.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/world/blocks/logic/LogicBlock.java b/core/src/mindustry/world/blocks/logic/LogicBlock.java index d8871484ff..a02a6864bf 100644 --- a/core/src/mindustry/world/blocks/logic/LogicBlock.java +++ b/core/src/mindustry/world/blocks/logic/LogicBlock.java @@ -318,9 +318,10 @@ public class LogicBlock extends Block{ //store any older variables for(Var var : executor.vars){ - if(!var.constant){ + boolean unit = var.name.equals("@unit"); + if(!var.constant || unit){ BVar dest = asm.getVar(var.name); - if(dest != null && !dest.constant){ + if(dest != null && (!dest.constant || unit)){ dest.value = var.isobj ? var.objval : var.numval; } } From cb3b43cc48051001048e662cdc49efbf0b30a052 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 14:23:29 -0500 Subject: [PATCH 06/13] Disabled cursor scaling --- core/src/mindustry/ui/Fonts.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/ui/Fonts.java b/core/src/mindustry/ui/Fonts.java index 91c7873f2d..5934f2e35f 100644 --- a/core/src/mindustry/ui/Fonts.java +++ b/core/src/mindustry/ui/Fonts.java @@ -67,7 +67,7 @@ public class Fonts{ } public static int cursorScale(){ - return Math.max(1, Mathf.round(Scl.scl(1f))); + return 1; } public static void loadFonts(){ From f6428b885772a0219f555dbe55f7746925482cea Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 16:40:54 -0500 Subject: [PATCH 07/13] Fixed #3808 --- core/src/mindustry/core/Logic.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index cffe8415bf..e468d82d56 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -243,8 +243,10 @@ public class Logic implements ApplicationListener{ } private void updateWeather(){ + state.rules.weather.removeAll(w -> w.weather == null); for(WeatherEntry entry : state.rules.weather){ + if(entry.weather == null) continue; //update cooldown entry.cooldown -= Time.delta; From bdbc9b865b774c447d3678f401ef46e786fcb35e Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 17:50:29 -0500 Subject: [PATCH 08/13] Fixed distort artifacts --- core/src/mindustry/core/World.java | 1 + .../maps/filters/GenerateFilter.java | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index a167a32ecb..45f014ad87 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -615,6 +615,7 @@ public class World{ GenerateInput input = new GenerateInput(); for(GenerateFilter filter : filters){ + filter.randomize(); input.begin(filter, width(), height(), (x, y) -> tiles.getn(x, y)); filter.apply(tiles, input); } diff --git a/core/src/mindustry/maps/filters/GenerateFilter.java b/core/src/mindustry/maps/filters/GenerateFilter.java index 6d7a00f3a9..07811c3baf 100644 --- a/core/src/mindustry/maps/filters/GenerateFilter.java +++ b/core/src/mindustry/maps/filters/GenerateFilter.java @@ -23,24 +23,27 @@ public abstract class GenerateFilter{ //buffer of tiles used, each tile packed into a long struct long[] buffer = new long[tiles.width * tiles.height]; - //save to buffer for(int i = 0; i < tiles.width * tiles.height; i++){ Tile tile = tiles.geti(i); - buffer[i] = PackTile.get(tile.blockID(), tile.floorID(), tile.overlayID()); + + in.apply(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay()); + apply(); + + buffer[i] = PackTile.get(in.block.id, in.floor.id, in.overlay.id); } + //write to buffer for(int i = 0; i < tiles.width * tiles.height; i++){ Tile tile = tiles.geti(i); long b = buffer[i]; - in.apply(tile.x, tile.y, Vars.content.block(PackTile.block(b)), Vars.content.block(PackTile.floor(b)), Vars.content.block(PackTile.overlay(b))); - apply(); + Block block = Vars.content.block(PackTile.block(b)), floor = Vars.content.block(PackTile.floor(b)), overlay = Vars.content.block(PackTile.overlay(b)); - tile.setFloor(in.floor.asFloor()); - tile.setOverlay(!in.floor.asFloor().hasSurface() && in.overlay.asFloor().needsSurface ? Blocks.air : in.overlay); + tile.setFloor(floor.asFloor()); + tile.setOverlay(!floor.asFloor().hasSurface() && overlay.asFloor().needsSurface ? Blocks.air : overlay); - if(!tile.block().synthetic() && !in.block.synthetic()){ - tile.setBlock(in.block); + if(!tile.block().synthetic() && !block.synthetic()){ + tile.setBlock(block); } } }else{ From b0f62f25e6e4bd1bc55cb275e5b4db3763d82a46 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 17:53:49 -0500 Subject: [PATCH 09/13] No suggested mods --- core/src/mindustry/Vars.java | 2 -- core/src/mindustry/ui/dialogs/ModsDialog.java | 8 ++------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index d5b9778f67..8269c05b06 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -47,8 +47,6 @@ public class Vars implements Loadable{ public static final int bufferSize = 8192; /** global charset, since Android doesn't support the Charsets class */ public static final Charset charset = Charset.forName("UTF-8"); - /** mods suggested for import */ - public static final String[] suggestedMods = {""}; /** main application name, capitalized */ public static final String appName = "Mindustry"; /** URL for itch.io donations. */ diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java index 3e26dd8c3a..a54d2fee59 100644 --- a/core/src/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/mindustry/ui/dialogs/ModsDialog.java @@ -105,13 +105,9 @@ public class ModsDialog extends BaseDialog{ t.button("@mod.import.github", Icon.github, bstyle, () -> { dialog.hide(); - var modString = Core.settings.getString("lastmod", ""); - var suggested = Structs.random(suggestedMods); - ui.showTextInput("@mod.import.github", "", 64, modString.isEmpty() ? suggested : modString, text -> { - if(!modString.isEmpty() || !Structs.eq(suggested, text)){ - Core.settings.put("lastmod", text); - } + ui.showTextInput("@mod.import.github", "", 64, Core.settings.getString("lastmod", ""), text -> { + Core.settings.put("lastmod", text); ui.loadfrag.show(); //Try to download the 6.0 branch first, but if it doesn't exist, try master. From d61bb66418f237caa0f022d51879cf17e41da2c7 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 18:03:21 -0500 Subject: [PATCH 10/13] Fixed capture wave being set to 0 in some situations --- core/src/mindustry/core/Control.java | 2 +- core/src/mindustry/game/SectorInfo.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index 047cdd575e..906acdd4b5 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -341,7 +341,7 @@ public class Control implements ApplicationListener, Loadable{ state.rules.waves = true; //reset win wave?? - state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null ? sector.preset.captureWave : state.rules.winWave > state.wave ? state.rules.winWave : 40; + state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null && sector.preset.captureWave > 0 ? sector.preset.captureWave : state.rules.winWave > state.wave ? state.rules.winWave : 40; //if there's still an enemy base left, fix it if(state.rules.attackMode){ diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index deb2ed4688..6a15c50e96 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -130,7 +130,7 @@ public class SectorInfo{ } //if there are infinite waves and no win wave, add a win wave. - if(waves && winWave <= 0 && !attack){ + if(winWave <= 0 && !attack){ winWave = 30; } From f9cfc8a2b861840ba54413bc4df4b50a87a04ed2 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 20:48:56 -0500 Subject: [PATCH 11/13] Fixed #3812 / Fixed #3813 --- core/assets/bundles/bundle.properties | 1 + core/src/mindustry/core/Logic.java | 52 ++++++++++++++++++- .../mindustry/ctype/UnlockableContent.java | 4 +- core/src/mindustry/io/TypeIO.java | 16 ++++++ .../mindustry/ui/fragments/HintsFragment.java | 1 + .../world/blocks/storage/CoreBlock.java | 23 ++++---- .../world/blocks/storage/StorageBlock.java | 14 ++--- desktop/src/mindustry/desktop/steam/SNet.java | 7 +-- 8 files changed, 93 insertions(+), 25 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 52feed8ca2..28d9af3072 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1283,6 +1283,7 @@ hint.guardian = [accent]Guardian[] units are armored. Weak ammo such as [accent] hint.coreUpgrade = Cores can be upgraded by [accent]placing higher-tier cores over them[].\n\nPlace a  [accent]Foundation[] core over the  [accent]Shard[] core. Make sure it is free from nearby obstructions. hint.presetLaunch = Gray [accent]landing zone sectors[], such as [accent]Frozen Forest[], can be launched to from anywhere. They do not require capture of nearby territory.\n\n[accent]Numbered sectors[], such as this one, are [accent]optional[]. hint.coreIncinerate = After the core is filled to capacity with an item, any extra items of that type it receives will be [accent]incinerated[]. +hint.coopCampaign = When playing the [accent]co-op campaign[], items that are produced in the current map will also be sent [accent]to your local sectors[].\n\nAny new research done by the host also carries over. item.copper.description = Used in all types of construction and ammunition. item.copper.details = Copper. Abnormally abundant metal on Serpulo. Structurally weak unless reinforced. diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index e468d82d56..bb91fc824e 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -153,6 +153,18 @@ public class Logic implements ApplicationListener{ } }); + //send out items to each client + Events.on(TurnEvent.class, e -> { + if(net.server() && state.isCampaign()){ + int[] out = new int[content.items().size]; + state.getSector().info.production.each((item, stat) -> { + out[item.id] = Math.max(0, (int)(stat.mean * turnDuration / 60)); + }); + + Call.sectorProduced(out); + } + }); + } /** Adds starting items, resets wave time, and sets state to playing. */ @@ -297,8 +309,46 @@ public class Logic implements ApplicationListener{ public static void researched(Content content){ if(!(content instanceof UnlockableContent u)) return; + var node = u.node(); + + //unlock all direct dependencies on client, permanently + while(node != null){ + node.content.unlock(); + node = node.parent; + } + state.rules.researched.add(u.name); - Events.fire(new UnlockEvent(u)); + } + + //called when the remote server runs a turn and produces something + @Remote + public static void sectorProduced(int[] amounts){ + if(!state.isCampaign()) return; + Planet planet = state.rules.sector.planet; + boolean any = false; + + for(Item item : content.items()){ + int am = amounts[item.id]; + if(am > 0){ + int sumMissing = planet.sectors.sum(s -> s.hasBase() ? s.info.storageCapacity - s.info.items.get(item) : 0); + if(sumMissing == 0) continue; + //how much % to add + double percent = Math.min((double)am / sumMissing, 1); + for(Sector sec : planet.sectors){ + if(sec.hasBase()){ + int added = (int)Math.ceil(((sec.info.storageCapacity - sec.info.items.get(item)) * percent)); + sec.info.items.add(item, added); + any = true; + } + } + } + } + + if(any){ + for(Sector sec : planet.sectors){ + sec.saveInfo(); + } + } } @Override diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java index 3ee5ac1ba8..a08dab1b67 100644 --- a/core/src/mindustry/ctype/UnlockableContent.java +++ b/core/src/mindustry/ctype/UnlockableContent.java @@ -117,7 +117,7 @@ public abstract class UnlockableContent extends MappableContent{ /** Makes this piece of content unlocked; if it already unlocked, nothing happens. */ public void unlock(){ - if(!net.client() && !unlocked()){ + if(!unlocked && !alwaysUnlocked){ unlocked = true; Core.settings.put(name + "-unlocked", true); @@ -135,7 +135,7 @@ public abstract class UnlockableContent extends MappableContent{ } public boolean unlocked(){ - if(net != null && net.client()) return alwaysUnlocked || state.rules.researched.contains(name); + if(net != null && net.client()) return unlocked || alwaysUnlocked || state.rules.researched.contains(name); return unlocked || alwaysUnlocked; } diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java index 58446a8018..d3172d378e 100644 --- a/core/src/mindustry/io/TypeIO.java +++ b/core/src/mindustry/io/TypeIO.java @@ -547,6 +547,22 @@ public class TypeIO{ return read.b(new byte[length]); } + public static void writeInts(Writes write, int[] ints){ + write.s((short)ints.length); + for(int i : ints){ + write.i(i); + } + } + + public static int[] readInts(Reads read){ + short length = read.s(); + int[] out = new int[length]; + for(int i = 0; i < length; i++){ + out[i] = read.i(); + } + return out; + } + public static void writeTraceInfo(Writes write, TraceInfo trace){ writeString(write, trace.ip); writeString(write, trace.uuid); diff --git a/core/src/mindustry/ui/fragments/HintsFragment.java b/core/src/mindustry/ui/fragments/HintsFragment.java index 7c7892b8ac..7380457837 100644 --- a/core/src/mindustry/ui/fragments/HintsFragment.java +++ b/core/src/mindustry/ui/fragments/HintsFragment.java @@ -173,6 +173,7 @@ public class HintsFragment extends Fragment{ && SectorPresets.frozenForest.sector.save == null, () -> state.isCampaign() && state.getSector().preset == SectorPresets.frozenForest), coreIncinerate(() -> state.isCampaign() && state.rules.defaultTeam.core() != null && state.rules.defaultTeam.core().items.get(Items.copper) >= state.rules.defaultTeam.core().storageCapacity - 10, () -> false), + coopCampaign(() -> net.client() && state.isCampaign() && SectorPresets.groundZero.sector.hasBase(), () -> false), ; @Nullable diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index e53bd84eff..b310a04b8b 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -6,6 +6,7 @@ import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; import arc.struct.*; +import arc.util.*; import mindustry.*; import mindustry.annotations.Annotations.*; import mindustry.content.*; @@ -246,17 +247,18 @@ public class CoreBlock extends StorageBlock{ } state.teams.registerCore(this); - storageCapacity = itemCapacity + proximity().sum(e -> isContainer(e) && owns(e) ? e.block.itemCapacity : 0); - proximity.each(e -> isContainer(e) && owns(e), t -> { + storageCapacity = itemCapacity + proximity().sum(e -> owns(e) ? e.block.itemCapacity : 0); + proximity.each(e -> owns(e), t -> { t.items = items; ((StorageBuild)t).linkedCore = this; }); for(Building other : state.teams.cores(team)){ if(other.tile() == tile) continue; - storageCapacity += other.block.itemCapacity + other.proximity().sum(e -> isContainer(e) && owns(other, e) ? e.block.itemCapacity : 0); + storageCapacity += other.block.itemCapacity + other.proximity().sum(e -> owns(e) && owns(other, e) ? e.block.itemCapacity : 0); } + //Team.sharded.core().items.set(Items.surgeAlloy, 12000) if(!world.isGenerating()){ for(Item item : content.items()){ items.set(item, Math.min(items.get(item), storageCapacity)); @@ -303,24 +305,19 @@ public class CoreBlock extends StorageBlock{ Draw.rect("block-select", t.x + offset * p.x, t.y + offset * p.y, i * 90); } }; - if(proximity.contains(e -> isContainer(e) && e.items == items)){ + if(proximity.contains(e -> owns(e) && e.items == items)){ outline.get(this); } - proximity.each(e -> isContainer(e) && e.items == items, outline); + proximity.each(e -> owns(e) && e.items == items, outline); Draw.reset(); } - - public boolean isContainer(Building tile){ - return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == this || ((StorageBuild)tile).linkedCore == null); - } - public boolean owns(Building tile){ - return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == this || ((StorageBuild)tile).linkedCore == null); + return owns(this, tile); } public boolean owns(Building core, Building tile){ - return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == core || ((StorageBuild)tile).linkedCore == null); + return tile instanceof StorageBuild b && (b.linkedCore == core || b.linkedCore == null); } public boolean incinerate(){ @@ -340,7 +337,7 @@ public class CoreBlock extends StorageBlock{ int total = proximity.count(e -> e.items != null && e.items == items); float fract = 1f / total / state.teams.cores(team).size; - proximity.each(e -> isContainer(e) && e.items == items && owns(e), t -> { + proximity.each(e -> owns(e) && e.items == items && owns(e), t -> { StorageBuild ent = (StorageBuild)t; ent.linkedCore = null; ent.items = new ItemModule(); diff --git a/core/src/mindustry/world/blocks/storage/StorageBlock.java b/core/src/mindustry/world/blocks/storage/StorageBlock.java index 7bfda601d1..1ead7b97ab 100644 --- a/core/src/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/mindustry/world/blocks/storage/StorageBlock.java @@ -91,14 +91,16 @@ public class StorageBlock extends Block{ @Override public void overwrote(Seq previous){ - for(Building other : previous){ - if(other.items != null){ - items.add(other.items); + //only add prev items when core is not linked + if(linkedCore == null){ + for(Building other : previous){ + if(other.items != null && other.items != items){ + items.add(other.items); + } } - } - //ensure item counts are not too high - items.each((i, a) -> items.set(i, Math.min(a, itemCapacity))); + items.each((i, a) -> items.set(i, Math.min(a, itemCapacity))); + } } @Override diff --git a/desktop/src/mindustry/desktop/steam/SNet.java b/desktop/src/mindustry/desktop/steam/SNet.java index 5d603067f3..03a32297c6 100644 --- a/desktop/src/mindustry/desktop/steam/SNet.java +++ b/desktop/src/mindustry/desktop/steam/SNet.java @@ -31,8 +31,8 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback, final NetProvider provider; final PacketSerializer serializer = new PacketSerializer(); - final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(1024 * 4); - final ByteBuffer readBuffer = ByteBuffer.allocateDirect(1024 * 4); + final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(16384); + final ByteBuffer readBuffer = ByteBuffer.allocateDirect(16384); final CopyOnWriteArrayList connections = new CopyOnWriteArrayList<>(); final IntMap steamConnections = new IntMap<>(); //maps steam ID -> valid net connection @@ -131,9 +131,10 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback, writeBuffer.limit(writeBuffer.capacity()); writeBuffer.position(0); serializer.write(writeBuffer, object); + int length = writeBuffer.position(); writeBuffer.flip(); - snet.sendP2PPacket(currentServer, writeBuffer, mode == SendMode.tcp ? P2PSend.Reliable : P2PSend.UnreliableNoDelay, 0); + snet.sendP2PPacket(currentServer, writeBuffer, mode == SendMode.tcp || length >= 1200 ? P2PSend.Reliable : P2PSend.UnreliableNoDelay, 0); }catch(Exception e){ net.showError(e); } From f9024e55009e9d798e82a0cbdb0f4f59f4c33885 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 21:14:10 -0500 Subject: [PATCH 12/13] Consider sectors with bases unlocked --- core/src/mindustry/ui/dialogs/PlanetDialog.java | 5 +++-- fastlane/metadata/android/en-US/changelogs/29766.txt | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/29766.txt diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 6df80b6311..3d323a9bc0 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -254,6 +254,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ boolean canSelect(Sector sector){ if(mode == select) return sector.hasBase(); + if(sector.hasBase()) return true; //preset sectors can only be selected once unlocked if(sector.preset != null){ TechNode node = sector.preset.node(); @@ -702,7 +703,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ stable.image().color(Pal.accent).fillX().height(3f).pad(3f).row(); - boolean locked = sector.preset != null && sector.preset.locked() && sector.preset.node() != null; + boolean locked = sector.preset != null && sector.preset.locked() && !sector.hasBase() && sector.preset.node() != null; if(locked){ stable.table(r -> { @@ -769,7 +770,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ return; } - if(sector.preset != null && sector.preset.locked()){ + if(sector.preset != null && sector.preset.locked() && !sector.hasBase()){ return; } diff --git a/fastlane/metadata/android/en-US/changelogs/29766.txt b/fastlane/metadata/android/en-US/changelogs/29766.txt new file mode 100644 index 0000000000..bccc1e789c --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/29766.txt @@ -0,0 +1,9 @@ +[This is a truncated changelog, see Github for full notes] +- Fixed certain sectors having infinite waves in very specific situations +- Fixed various crashes +- Fixed community servers not displaying on Linux +- Fixed some logic UI bugs +- Fixed Distort filter not working in map post-generation +- Fixed clients in multiplayer not getting item unlocks +- Fixed enemy AI blocking ground unit paths in some circumstances +- Made night in campaign slightly less dark From 29fe5dab0686b522af9c30f3cfa38074ce94f571 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 5 Dec 2020 21:24:27 -0500 Subject: [PATCH 13/13] Allow client research --- .../mindustry/ui/dialogs/ResearchDialog.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/core/src/mindustry/ui/dialogs/ResearchDialog.java b/core/src/mindustry/ui/dialogs/ResearchDialog.java index 49701dbe76..f78d98e77b 100644 --- a/core/src/mindustry/ui/dialogs/ResearchDialog.java +++ b/core/src/mindustry/ui/dialogs/ResearchDialog.java @@ -172,16 +172,6 @@ public class ResearchDialog extends BaseDialog{ }); } - @Override - public Dialog show(){ - if(net.client()){ - ui.showInfo("@research.multiplayer"); - return this; - } - - return super.show(); - } - void treeLayout(){ float spacing = 20f; LayoutNode node = new LayoutNode(root, null); @@ -439,6 +429,14 @@ public class ResearchDialog extends BaseDialog{ void unlock(TechNode node){ node.content.unlock(); + + //unlock parent nodes in multiplayer. + TechNode parent = node.parent; + while(parent != null){ + parent.content.unlock(); + parent = parent.parent; + } + checkNodes(root); hoverNode = null; treeLayout();