결합된 상자(가칭) 만들어 보는중


윗 글을 쓴지도 벌써 3개월이 훌쩍 넘어버렸는데 중간에 딴겜하느라 못한것도 있지만

생각보다 예외 처리를 해야할게 너무많아서 이걸 정리 못하고 있는 이유도 상당히 크다


생각을 정리해볼 겸 해서 쓰는 글


Flexible chest의 동작원리 대전재는

1. 상하좌우로 인접하여있으면 같은 link_id를 부여하여 하나의 상자처럼 취급하여야 한다.

2. 연결이 끊어지면 link_id또한 분리하여 다른 상자 취급이 되어야 한다.

3. 아이템이 사라지는 경우가 발생하면 안된다.


어찌보면 단순하지만 이 과정에서 여러 문제점들이 생긴다...


1. 새로운 상자가 추가되고 인접한 면이 딱 1개인 경우


이 경우는 특별히 고려할게 없다. 그냥 인접한 한면의 link_id를 그대로 복사하여 사용하면 끝


2. 새로운 상자가 추가되고 인접한 면이 하나도 없는 경우

이 경우는 지금까지 부여한적이 없는 link_id를 상자에 부여해주면 된다


3. 새로운 상자가 추가되고 인접한 면이 2개 이상인 경우

여기부턴 이야기가 복잡해진다

처음에 철이 들어있던 상자의 id를 A라 하고, 구리가 들어있던 상자의 id를 B라고 한다면 저 두개를 이었을 경우 3개의 상자는 어떤 link_id를 가져야 할까?

3-a. 더 많은 아이템이 들어있는 link_id 우선

3-b. 더 많은 상자로 이루어진 link_id 우선

3-c. 더 작은 값의 link_id 우선

3-d. A도 B도 아닌 새로운 link_id C
고를 수 있는 선택지가 여럿 있는데 일단 나는 3-b를 고려하고 있다.


3-A. 새로운 상자가 추가되고 인접한 면이 2개 이상인 경우인데 템이 너무 많이 들어있는 경우


현재 Flexible chest는 총 48스택의 아이템을 보관할 수 있다.

만약 두 개의 상자 A와 B에 담긴 아이템이 총 수량이 48스택 이하라면 link_id를 하나로 합치는 과정에서 하나의 link_id로 모든 아이템을 몰아 넣을 수 있기 때문에 별 문제가 없다

그런데 그렇지 않다면?


왼쪽 상자에는 철이 30스택, 오른쪽 상자에는 구리가 30스택이 들어있다

이때 저 두 상자 사이에 새로운 상자를 추가하려고 한다면 어떻게 해야할 것인가?


3-A-a. 48스택을 초과하는 부분의 아이템은 삭제한다

3-A-b. 48스택을 초과하는 부분의 아이템을 바닥에 뿌린다(!)

3-A-c. 상자의 설치 자체가 불가능하게 막는다(구현 가능한지 모르겠음)

3-A-d. 상자가 설치되면 과부하 판정을 일으키면서 상자를 바닥에 아이템 형태로 뿌린다.


나는 c안이 된다면 참 좋을 것 같기는 하지만 이걸 모딩으로 구현할 수 있을지는 모르겠어서 d안을 선택하게 되지 않을까 싶음


상자를 설치할 때 생기는 이슈는 이정도고 제거로 넘어가게 되면 더 어려운 문제들이 생겨난다


4. 상자가 제거되고 인접한 면이 딱 1개인 경우

가장 심플한 경우로, 딱히 처리할게 없다


5. 상자가 제거되고 인접한 면이 하나도 없는 경우(최후의 상자)

이 경우는 생각할 것이 생긴다

이 상자는 일반 상자가아닌 Linked Chest이기 때문에 저 상태에서 그냥 철거를 하게 된다면 상자 속 아이템이 인벤토리로 들어오지 못하고 그냥 상자만 철거 되게 된다

즉 상자 속 아이템이 그대로 유실되어 버림

이를 막기 위해서는


5-a. 최후의 상자일 경우 상자속 아이템을 스크립트를 이용하여 전부 캐릭터 인벤토리로 전송한다

5-b. 최후의 상자가 되는 시점에 그 즉시 상자를 linked chest에서 일반 상자로 교체한다


5-a를 고른다면 캐릭터 인벤토리가 가득 차버렸을때 어떻게 해야할지 또 결정해야한다.

5-a-a. 인벤토리 초과분은 바닥에 뿌린다

5-a-b. 인벤토리에 옮길 수 있는 만큼만 전송하고, 해체는 거부한다.


5-a-b가 자연스러운 동작이긴 하지만 해체를 거부한다는것 자체는 구현하기가 좀 난해한 부분이 있음(3-A-c 처럼)


5-b는 애초에 상자가 2개 남은상태에서 하나를 해체한다면 나머지 하나를 그 즉시 일반 상자로(모양은 똑같은) 바꿔치기 하는거임

이러면 바닐라 상자 취급이라 해체를 하려고 해도 알아서 5-a-b처럼 동작할 수 있다.


다만 5-b를 선택하려면 2번 케이스에서 완전 새로운 상자를 설치할 때는 linked chest로 설치하는 것이 아니라 일반 바닐라 상자로 설치를 한 다음 그 주위에 인접하여 새로운 상자를 설치할 때 그제서야 linked chset로 교체하는 기법을 적용하여야 함



머리가 아프다


6. 상자가 제거되고 인접한 면이 2개 이상인 경우

(철이 300개, 구리가 300개 들어있다고 가정)

이것도 3의 상황과 비슷한 경우라고 할 수 있다

연결되어있던 상자들의 허리를 끊을 경우 id를 분리해주어야 하는데 그럼 템들은 어떻게 분배되어야 할까?


6-a. 더 많은 상자로 이루어진 쪽으로 아이템을 전부 몰아준다


(왼쪽 상자에 철300개 구리300개)


6-b. 아이템을 N빵하여 나눈다

(왼쪽 상자에 철150,구리150, 오른쪽 상자에 철150,구리150)


6-c. 아이템을 상자 갯수에 비례하여 나눈다


(왼쪽 상자에 철200,구리200, 오른쪽 상자에 철100,구리100)


처리하기는 a안이 쉽긴한데 좀더 귀찮더라도 c안을 해야하지 않나 싶다

아니면 글 쓰면서 추가로 생각난건데 d안이 있다


6-d. 아이템을 상자 갯수에 비례하여 나눔과 동시에 템을 1/N은 회수한다.


(왼쪽 상자에 철150,구리150, 오른쪽 상자에 철75,구리75 + 인벤토리로 철75,구리75 들어옴)


d안은 나름 합리적일 수도 아니면 그냥 귀찮기만 한 수일 수도 있다. 고민좀 해봐야할듯

d안을 적용한다면 4번 케이스에서 인접한 면이 한 면인 경우에도 템을 부분적으로 회수하는 식으로 해야 한다.





여기까진 손으로 설치하고 해체하는 것에 관련된 내용이였다

하지만 팩토리오에는 청사진과 건설 로봇이 있기 때문에 이에 대한 고민을 추가로.. 해주어야한다...




7. 청사진을 이용하여 상자를 설치한다면?


7-a. 고스트가 설치되는 시점에 설치(1,2,3 케이스) 작업을 한다.

7-b. 실제로 로봇이 설치하는 시점에 설치 작업을 한다.


사실 이건 고민포인트가 아니고 당연히 b로 해야한다. 실제로 연결된 것도 아닌데 같은 link_id로 연결해버리는것은 뭔가 이상한다.


8. 해체계획기 이용하여 상자를 해체한다면?

8-a. 해체가 예약되는 시점에 해체(4,5,6 케이스) 작업을 한다.

8-b. 실제로 로봇이 해체하는 시점에 해체 작업을 한다.


이건 7번 케이스보단 조금 생각이 필요해보인다.


바닐라의 경우에는 해체가 예약되는 즉시 동작을 멈추기 때문에 이경우에도 a안을 선택해서 해체가 예약되는 즉시 id를 끊는 것이 합리적으로 보인다

a안을 고를 경우 봐야 하는 케이스가 하나 더 있다(9번 케이스)


8-A. 로봇은 상자 안에 템을 먼저 가져가고 상자를 철거해야함

5번 케이스랑 비슷한 이야기로, 기본적으로 linked chest에 해체계획기를 사용하게 된다면 로봇은 그안에 템이 있는지 없는지 신경 쓰지 않고 오로지 상자만 철거하게 된다

해체 계획하고자 하는 상자가 가장 마지막 최후의 상자인 경우 이 상자가 반드시 linked chest가 아닌 바닐라 상자일 필요성이 있다

5-b안을 골랐을 경우는 별 문제 없이 해결되는 문제이고, 5-a안을 골랐다면 해체 계획 시점에 바닐라 상자로 교체를 반드시 해주어야 로봇이 먼저 속에 있는 아이템을 회수 할 수 있게 된다

쓰다보니 걍 5-b안을 사용해야겠다는 생각이 강해지는 중


만약 6-d안을 고른 경우에도 linked chest에 해체계획시에는 바닐라 상자로 교체를 하면서 1/N에 해당하는 아이템을 바닐라 상자속에 넣어준 후 이 상자에 해체계획이 걸리도록 해주어야 한다.


9. 해체 예약을 취소하는 경우

8-a안을 골라서 해체가 예약된 즉시 해체 취급을 할 것이라면

해체 예약을 취소하는 경우는 반대로 설치하는 것과 동일한 작업(1,2,3)을 잊지 않고 해주어야 한다.


9-A. 해체 예약을 취소했는데 이때 3-A번케이스(스택초과)가 발생하면 어캄?

9-A-a. 48스택을 초과하는 부분의 아이템은 삭제한다

9-A-b. 48스택을 초과하는 부분의 아이템을 바닥에 뿌린다

9-A-c. 상자의 해체 예약 취소를 취소시켜버린다

9-A-d. 과부하 판정을 일으키면서 상자를 바닥에 아이템 형태로 뿌린다.


3-A에서 고른 것과 같은 쌍으로 고르게 될 듯





청사진/해체계획기를 쓰기 시작할 경우 손으로 설치하는 것과는 다르게 동일 틱에 여러개의 아이템이 설치/해체 될 수 있기 때문에 이로인해 문제가 발생하지 않는지에 대해서도 확실히 체크를 해주어야 한다


10. 업그레이드 계획기?

다행이 이 모드에서 업그레이드 계획기는 들어갈 껀덕지가 없다

다만 밸트밸런서 모드를 만들게 되고 이때 밸런서의 티어를 나누게 된다면 고민이 필요해 질 수도 있다




여기까지만 하고 때려치고 싶지만 봐야할 케이스가 더 있다



우리의 친구 바이터들이 고오얀놈 하는 케이스를 봐야한다.


11. 상자가 파괴된 경우


파괴는 해체와는 조금 다르다

해체의 경우는 아이템의 손실이 없이 모조리 회수가 되어야 하지만 파괴되는 경우는 아이템이 일부 손실이 되는 식으로 구현을 해야한다.


11-a. 최후의 상자일 때만 아이템을 유실 시킨다.

11-b. 상자의 갯수가 N개라면 1/N 아이템을 유실 시킨다.


아이템의 유실여부를 따지는 것을 제외하면 기본적으로는 해체와 비슷한 작업을 해주면 될듯함

11-a는 6-a,b,c랑 궁합이 잘 맞고 11-b는 6-d랑 궁합이 잘 맞아보인다

나는 11-b가 좀 더 괜찮다고 생각한다



12. event 정리(https://lua-api.factorio.com/latest/events.html)

설치와 관련된 이벤트

on_built_entity

on_cancelled_deconstruction

on_entity_cloned

on_pre_build

on_robot_built_entity

on_trigger_created_entity

script_raise_built


해체와 관련된 이벤트

on_entity_destroyed

on_player_mined_entity

on_pre_player_mined_item

on_robot_mined

on_robot_mined_entity

on_robot_pre_mined

script_raise_destroy


파괴와 관련된 이벤트

on_chunk_deleted

on_pre_chunk_deleted

on_entity_died

on_pre_surfcae_cleared

on_pre_surfcae_deleted

on_surface_cleared

on_surface_deleted


몇몇 이벤트는 무시해도 될듯하지만 무시하기 힘든 이벤트들도 있어서 누락되지 않도록 주의해야 할듯

청크 삭제같은건 그냥 무시하고 싶은데 우탐모 하다보면 저런 기능도 쓰는 것 보면 대응을 해야할 것 같기도 해서 머리가 아프다



그래도 나름 이렇게 글 쓰면서 어느정도 정리가 되기는 하니까 안 정해진 선택포인트들만 정하고 난 후 무지성으로 하나하나 구현하면 될 것같긴함

얼마나 걸릴려나 감이 안오네