들어가며
note.project-record
시작하며
- README.md에 써놓기에는 주저리 주저리 뒷썰같은 느낌.
- 필요한 것만 들어가는 간결한 프로젝트와는 다른 뭔가가 필요했다.
시도
저장소 이름 짓는게 귀찮았다. gpt 무료버전을 사용해봤다.
project-log
retrospect
post-mortem
knowhow
lab-notes
dev-journey
여러가지가 나왔는데. retrospect / post-mortem는 왠지 끝나고 하는 느낌이라 도중에도 적는 느낌이 안나 제외.
일단 저장소 이름을 note.dev-journey 해서 한글 타이틀을 정하는데 study.dev-notes의 한글 타이틀이 넷평의 개발 노트 였다.
뭔가 dev도 중복되고 journey가 가지고있는 여행의 느낌이 맘에 안들었다. 그래서 한글 타이틀을 건조하게 넷평의 프로젝트 기록이라 먼저 정하고 영문 저장소 이름을 정했다. note.project-record
이모지도 정하고 싶었는데
- 📄는 이미 study.에서 쓰고 있다
- 📓도 note라서 생각했지만, 팬을 넣는게 좀 더 느낌이 있어 보인다.
- 📝도 팬이 달려있어 고려해봤는데 종이장이 study.에서 쓰이는 거랑 겹친다.
- ✒️ 펜촉을 써본적이 없지만. 뭔가 느낌이 있어 노트의 아이콘은 이걸로 하겠다.
언어코드 ko ! kr ??
어느날 다른 공부 노트쪽에 PR이 올라왔다. 그냥 한국이니까 kr썼는데
- https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
- kr - https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php?SearchType=iso_639_1&SearchTerm=kr
- 나이지리아 카누리(Kanuri) 민족
- kr - https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php?SearchType=iso_639_1&SearchTerm=kr
아…. ko로 가야 맞는거구나… 여튼 어디서 유입이 되었는지 모르겠지만 PR이 와서 감사했다.
🎨 unity.webp
- https://www.google.com/search?q=steamdb+%22unity.webp%22
🔑 unity.libsodium
💾 SqlCipher4Unity3D
https://github.com/sqlkata/querybuilder/
https://netpyoung.github.io/study.dotnet/dotnet/PInvoke.html 참고
NF.Tool.UnityPackage
시작하며
- 유니티 패키지에 있는 파일들을 쉽게 확인하고 싶었다. (이미자, 사운드 등등)
- 드레그 드랍으로 쉽게 만들고 싶었다.
결정
- winform 아니면 WPF 아니면 Maui
- 간단하게 만들거라 winform으로.
- 나중에 크로스플렛폼이 되는 Maui로 하면 어떨까? 너무 무겁나?
unitypackage경로
| os | path |
|---|---|
| win | C:\Users{User}\AppData\Roaming\Unity\Asset Store-5.x |
| mac | ~/Library/Unity/Asset\ Store/ |
| linux | ~/.local/share/unity3d/Asset Store-5.x/ |
기타
- pack : yaml
- unpack: tar/gzip
Ref
tar-cs https://code.google.com/archive/p/tar-cs/ https://learn.microsoft.com/ko-kr/dotnet/api/system.formats.tar.tarfile?view=net-8.0
unity yaml이 key:value쌍이 맞지 않는 것도 있음. YamlDotNet https://github.com/aaubry/YamlDotNet 에서 파싱 오류 - 엄격한 검사
https://github.com/TwoTenPvP/UnityPackager 기반
avaloniaui 한번 적용해봤으나 Winform버전은 800Kb 언더라면, avaloniaui로 40Mb 가 나옴.
https://github.com/icsharpcode/SharpZipLib SharpZipLib을 System.Formats.Tar - TarFile로 대채 YamlDotNet 파싱 오류도 있고, 어차피 guid만 얻어오는 부분만 쓰고 있어서 YamlDotNet을 걷어내니
- 800kb가 200kb로 줄어듬
NF.Tool.ReleaseNoteMaker
시작하며
- 히스토리에서 뽑는건 별로
- ADR같은 도구가 있으면 좋겠다.
- towncrier을 찾았다.
기록
라이브러리 결정
-
AnsiConsole
- public override string StackTrace { get; } 안먹히는것.
- stderr AnsiConsole 어떻게 처리할고
- MultiSelectionPrompt 해서 키를 입력받아 캔슬 넣고싶었는데 캔슬이 없네?
- Select는 있는데 SelectAll/DeselectAll이 없네
- https://github.com/spectreconsole/spectre.console/discussions/700
- 최대길이
- AnsiConsole.Profile.Width = 255;
-
Tomlyn 사용법
- array를 키를 지정해서 dic으로 넣는 기능이 있으면 좋을것같은데…
-
집합연산 까먹네
- https://learn.microsoft.com/en-us/dotnet/csharp/linq/standard-query-operators/set-operations
- 표로 정리했다가 그냥 그때그때 검색하자. 나중에 필요하면 다시 표로정리.
-
public void Deconstruct(out string fname, out string lname)
-
구조체 생성자 방지
- public ObsoleteAttribute(string? message, bool error)
- throw new InvalidOperationException
- public ObsoleteAttribute(string? message, bool error)
렌더템플릿 및 라이브러리 선택
visual studio에서 디버깅이 되는거에 가중치를 많이 줌.
- t4
- 디버깅 가능한걸로
- mono t4 디버깅 꽤 괜찮네, 근데 string넘기는게 아니라 filepath라 찝찝
- razor
- 아직 관리가 되지 않는듯 : https://github.com/adoconnection/RazorEngineCore/pull/148
- razor로도 template만들어 봤는데 의외로 t4보다 가시성이 안좋았다.
- liquid
- towncrier는 Jinja2
- 일단 liquid를 넣긴 넣었는데 t4가 더 나아보여서 삭제할까 보류중 => 혹시나 다른 사람들이 쓰면 돌이키기 힘드니 빠른 삭제로 결정.
- fluid / scriban / dotliquid
- dotliquid는 Drop만드는게 귀찮아서 패스
- https://github.com/microsoft/semantic-kernel/issues/6233 에서 scriban대신 fluid쓰는거보고 fluid로 선택
- liquid를 지원했으나 whitespace관리가 어렵고 fluid에서 class의 method호출이 안되었다.
- 안되서 {%- assign categoryIssues = category.GetAllIssues() -%}
- 이렇게 함 {%- assign categoryIssues = category.CategoryIssues -%}
네이밍
-
towncrier
- 다이나믹 언어 타입 및 네이밍 문제 - 저쪽 세상 네이밍 센스 맘에 안듬.
-
PatchNoteMaker 했는데… ReleaseNoteMaker 도 있는데…
- PatchNoteMaker했다가 최종적으로 ReleaseNoteMaker로 결정.
기타
-
assemblyLocation empty
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>- 이 옵션을 사용하면 애플리케이션의 모든 콘텐츠 파일(예: DLL, 구성 파일, 리소스 파일 등)이 실행 파일 내에 포함되어 실행 파일을 실행하면 자동으로 추출되고 실행됩니다.
- https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview?tabs=cli
-
line ending 문제
-
TestInitialize/TestCleanup/DeploymentItem/TestMethod
- DeploymentItem들이 TestInitialize보다 먼저 실행되는데 막상 TestContext.DeploymentDirectory는 동일해서 파일조작 테스트는 오작동을 일으킬 가능성이 생김.
- public required TestContext TestContext { get; set; } 로 가져와서 시작시 폴더이동.
-
docfx
[!INCLUDE [<title>](<filepath>)][!code-<language>[](<filepath><query-options>)]mermaid- NOTE / TIP / IMPORTANT / CAUTION / WARNING
> [!NOTE]
> Information the user should notice even if skimming.
- pack 시 define flag를 알 수 없네..
- reno라는 것도 있네?
.tt vs .t4
- 확장자를 .tt로 했다가 t4로 했다가 다시 tt로.
- 처음에 찾아봤을때 t4 template가 어감에 감겨 찾아봤다가 .tt가 많이 쓰인다는 사실을 알고 .tt로 결정
- 후에 까먹어서 왜 .tt야라고 생각하고 t4가 맘에 들어서 .t4로 변경
- 후에 또 뭔가 쌔해서 다시 찾아보고 .tt로 롤백
잡다한
- filename => fileName
- https://stackoverflow.com/questions/159017/named-string-formatting-in-c-sharp
- python textwrap
- https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/raw-string-literal
- 러스트로 작성된 것도 있네?
- https://github.com/nekitdev/changelogging
- draft대신 preview라는 명령어를 넣은건 좋은듯. https://docs.rs/changelogging/latest/changelogging/#preview
- https://github.com/nekitdev/changelogging
- https://github.com/twisted/towncrier
- https://devguide.python.org/core-team/committing/index.html#what-s-new-and-news-entries
- https://docs.gitlab.com/development/changelog/
- https://github.com/miniscruff/changie
nf-tool-release-note-maker-vscode
- https://marketplace.visualstudio.com/items?itemName=netpyoung.nf-tool-release-note-maker-vscode
- https://github.com/netpyoung/nf-tool-release-note-maker-vscode
시작하며
- NF.Tool.ReleaseNoteMaker을 커맨드라인으로 확인하려니 불편
- 에디터는 VSCode가 대세
참고
- get-started/your-first-extension
- yeoman
- 템플릿 기반 프로젝트 생성기(스캐폴딩 도구)
npx --package yo --package generator-code -- yo code- yo, generator-code 패키지를 활용하면서 yo code 명령어 실행
- microsoft/vscode-generator-code
- 아직 bun을 지원안하네 https://github.com/microsoft/vscode-generator-code/pull/475
- microsoft/vscode-vsce
- @vscode/vsce
- The Visual Studio Code Extension Manager
- Access Token 생성 - https://azure.microsoft.com/services/devops/
- Publisher 등록 - https://marketplace.visualstudio.com/manage/createpublisher
- https://marketplace.visualstudio.com/VSCode > Publish extensions > Create Publisher
기록
배포
vsce package - 패키지 파일로 만듬 - 후 에 파일을 통해서 배포도 가능
vsce login
- publish대신 vsce package 로 패키지 파일을 사이트에서 수동 업로드.
- 뭔가 마음이 놓인다.
네이밍 실수 nf-tools-release-note-maker-vscode => nf-tool-release-note-maker-vscode
- 나는 툴에 대해 단수 tool을 썼는데 까먹고 복수형인 tools를 붙여버렸다.
- nf-tools-release-note-maker-vscode - NF.Tool.ReleaseNoteMaker 이름이 안맞는 문제가 생겼는데,
- vscode extension market에 올려져 있어 그냥 유지할까 생각도 했지만,
- 인스톨횟수가 2회(내가 테스트용으로 한것)밖에 없고,
- nuget과는 달리 삭제가 가능해서 과감히 삭제후 이름바꾸고 다시 마켓에 업로드
- 처음 tools로 업로드 했을시에는 5분만에 Verifing이 끝나더니만, 이전 툴을 삭제하고 바로 tool로 올린 탓인지 1시간 정도 걸렸네
폴더구조를 바꾸려니 symbolic link가 필요하네
New-Item -ItemType SymbolicLink -Path “./nf-tools-release-note-maker-vscode/README.md” -Target “../README.md” New-Item -ItemType SymbolicLink -Path “./nf-tools-release-note-maker-vscode/LICENSE.md” -Target “../LICENSE.md” New-Item -ItemType SymbolicLink -Path “./nf-tools-release-note-maker-vscode/CHANGELOG.md” -Target “../CHANGELOG.md”
VSCode 멀티인풋을 하려면 webview가 필요하네
- https://github.com/Microsoft/vscode-extension-samples/tree/main/webview-sample
- framework가져다 쓸까하다가 그냥 gpt한테 심플하게 만들어달라고 해서 만듬
- https://github.com/microsoft/vscode-webview-ui-toolkit - deprecated
- https://vscode-elements.github.io/
- https://github.com/vscode-elements/elements
- https://fast.design/
- https://lit.dev/
webview event
<script>
const vscode = acquireVsCodeApi();
// 1) 버튼 클릭 시 확장으로 메시지 보내기
document.getElementById('send').addEventListener('click', () => {
vscode.postMessage({ command: 'alert', text: 'Hello from Webview!' });
});
// 2) 확장에서 온 메시지 받기
window.addEventListener('message', event => {
const message = event.data;
switch (message.command) {
case 'init':
console.log('Message from extension:', message.data);
break;
}
});
</script>
기타
-
흠 나중에 wasm파일 쓸 일 있으면 한번 여기서 테스트 해보고 싶네
-
activationEvents는 정적으로만 지정 가능 → configuration 기반 동적 활성화는 불가
-
폴더에 파일이 존재하면 메뉴가 생겨서 우클릭해서 확인하고싶었지만, Explorer에서 폴더를 선택할 때마다 발생하는 이벤트는 없음
-
ReleaseNote.config.toml 우클릭 임시파일에 preview를 쓰고 마크다운 렌더
-
resourceFilename == ReleaseNote.config.toml
-
ReleaseNote.config.toml를 config쪽으로 빼야겠네
-
https://code.visualstudio.com/api/references/when-clause-contexts#inspect-context-keys-utility
bun add --global yo generator-code
yo code Hello2 --extensionType=ts --pkgManager=npm --skip-install --gitInit=true --bundler=esbuild --skipOpen
node_modules/@types/vscode/index.d.ts.
package.json
"contributes": {
"commands": [
{
"command": "helloworld.helloWorld",
"title": "Hello World"
}
]
},
const disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => {
vscode.window.showInformationMessage('Hello World!');
});
context.subscriptions.push(disposable);
"menus": {
"explorer/context": [
{
"command": "myExtension.processFolder",
"when": "explorerResourceIsFolder",
"group": "navigation"
}
]
}
- https://github.com/shd101wyy/markdown-preview-enhanced
- https://github.com/dev-jonghoonpark/ettk-vscode-extention/
- https://esbuild.github.io/
- https://github.com/evanw/esbuild
- https://bun.com/docs/bundler/esbuild
- Error: Invalid problemMatcher reference: $esbuild-watch
- https://marketplace.visualstudio.com/items?itemName=connor4312.esbuild-problem-matchers
.vscodeignore - VS Code 확장(VSIX) 배포용 필터 파일
.vscode/extensions.json “recommendations”: [“dbaeumer.vscode-eslint”, “connor4312.esbuild-problem-matchers”, “ms-vscode.extension-test-runner”]
when 조건식은 정적 컨텍스트키만 됨 https://code.visualstudio.com/api/references/when-clause-contexts
- when 조건식 기반
- setContext 기반 https://code.visualstudio.com/api/references/commands
resourceExtname
https://code.visualstudio.com/docs/languages/markdown
await vscode.commands.executeCommand(‘markdown.showPreviewToSide’, tmpUri);
await vscode.commands.executeCommand(‘markdown-preview-enhanced.openPreview’, doc.uri);
https://github.com/BetterThanTomorrow/joyride 도 있네
“activationEvents”: [“onStartupFinished”],
https://code.visualstudio.com/api/references/activation-events#workspaceContains
“activationEvents”: [ “workspaceContains:**/.editorconfig” ]
“activationCommands”: { “atom-workspace”: “markdown-preview-enhanced:toggle” }, “activationHooks”: [
https://code.visualstudio.com/api/references/contribution-points#contributes.menus https://code.visualstudio.com/api/references/contribution-points#contributes.submenus
https://github.com/microsoft/vscode-extension-samples 예제
DeprecationWarning: The punycode module is deprecated. Please use a userland alternative instead.
"contributes": {
"commands": [
],
"menus": {
"explorer/context": [
],
"editor/context": [
]
}
}
— 설정
"contributes": {
"configuration": {
"title": "My Extension Settings",
"properties": {
"myExt.enableFeature": {
"type": "boolean",
"default": true,
"description": "Enable or disable the special feature (토글)"
},
"myExt.customMessage": {
"type": "string",
"default": "Hello!",
"description": "Set a custom message (문자열 입력)"
}
}
}
}
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
const config = vscode.workspace.getConfiguration('myExt');
const isEnabled = config.get<boolean>('enableFeature');
const message = config.get<string>('customMessage');
if (isEnabled) {
vscode.window.showInformationMessage(`Feature is enabled! Message: ${message}`);
}
// 설정 변경 감지
vscode.workspace.onDidChangeConfiguration(event => {
if (event.affectsConfiguration('myExt.enableFeature') || event.affectsConfiguration('myExt.customMessage')) {
const newConfig = vscode.workspace.getConfiguration('myExt');
const newEnabled = newConfig.get<boolean>('enableFeature');
const newMessage = newConfig.get<string>('customMessage');
vscode.window.showInformationMessage(`Updated! Enabled: ${newEnabled}, Message: ${newMessage}`);
}
});
}
https://code.visualstudio.com/api/references/contribution-points#contributes.configuration
예제에선 값이 딕셔너리인데, id를 포함한 어레이로 바꾸면 트리형태로 추가됨 - https://github.com/dotnet/vscode-csharp/blob/main/package.json “configuration”: { “title”: “My Extension Settings”,
"configuration": [
{
"title": "My Extension Settings",
"id": "a.a.a1",
https://github.com/qjebbs/vscode-plantuml https://github.com/BetterThanTomorrow/calva
Pulumi
await vscode.window.showQuickPick - 상단 선택 vscode.window.showInformationMessage - 우측 하단 yes, no
TODO
아이콘
https://code.visualstudio.com/api/references/extension-manifest
html을 그냥 문자열로 박아놨는데 뭔가 방법이 없을까?
https://medium.com/@sampsonjoliver/importing-html-files-from-typescript-bd1c50909992
🌶️ NF.Tool.ExcelFlow
-
https://github.com/netpyoung/nf.data-flow
- assembly로드 하는것까지 했음
-
partial db 갱신도
- excel을 winform에 드래그하면 그 엑셀에꺼만 갱신
-
Razor page
-
Attr지정
-
클라랑 서버 데이터 분리
-
타입지정
validate
- table column 이름 중복 - 알려주기
???
- unique id같은경우 알려주기?
템플릿은 T4로 C#함수를 쓸 수 있는
// sheet / enums / consts / class https://marketplace.visualstudio.com/items?itemName=bricelam.T4Language
const
CONST
| Type | Name | Value | Desc |
|---|---|---|---|
| int | n1 | 1 | hello |
Enum
E_ENUM
| Name | Value | Desc |
|---|---|---|
| n1 | 1 | hello |
| > | n1 | hello |
https://shd101wyy.github.io/markdown-preview-enhanced/#/markdown-basics?id=table
{ “markdown-preview-enhanced.enableExtendedTableSyntax”: true, }
셀 합치니까 멀티라인시 표가 안늘어나네? ‘AutoFit Row Height’ on merged cells
class
| ATTR | [PrimaryKey] | [Unique] |
| TYPE | int | int |
| NAME | id | character_id |
| DESC | ||
| VALUE | 1 | 1 |
tableroot/ Defines/ Const_1.xlsx Const_2.xlsx Enum_1.xlsx Enum_2.xlsx Hello/ Hello_1.xlsx Hello_2.xlsx
참조 상대경로로 해도 =‘[ComponentsC.xlsx]Sheet1’!A1 => 결국 절대경로로 되어버림
외부 파일과 참조 파일이 동시에 열려 있을 때만 상대경로 사용 가능 - INDIRECT / VLOOKUP https://stackoverflow.com/questions/11629633/how-do-i-make-a-relative-reference-to-another-workbook-in-excel
나중에 git 커밋마다 비교하면서 수정내역 알 수 있으면 좋겠네
- 누가
- 언제
- 파일
- 시트
- 내용
NPOI는 수식평가 외부참조가 안됨
- This workbook contains link to one or more external sources that could be unsafe.
- File > Info > Edit Links to Files > 톱니바퀴 > Always Refresh
) https://excel-dna.net/
sqlite 추출 json 추출
#Comment ? $Comment $는 엑셀에서 자주쓰는것이므로 쓰지말자
&END ? :END
client - 클라 전용 server - 서버 전용 빈칸 - 둘다 공용
-
같은 값으로 머지한것도 지원
-
셀에 대한 Note기능은 활용하지 않는걸로
_ignore
[Unique] [PrimaryKey]
예제 Type id 다른시트 참조
Const / Enum / 클래스
클래스 상속 금지
https://iekill.tistory.com/41
-
https://github.com/catsnipe/XlsToJson
- json/scriptableobject
-
https://github.com/cathei/BakingSheet
- enum이랑 dictionary다루는게 신기했었는데 지금보면 별로인 접근방식
-
https://github.com/elky84/ExcelToDotnet **
-
https://github.com/qingfeng346/ScorpioConversion
- bytes 二进制数据,支持 base64:// file:// https://github.com/kimsama/Unity-QuickSheet https://github.com/hnb-rabear/excel-to-unity
- winform 툴
- BouncyCastle.Crypto
- BouncyCastle.Cryptography
- markdig
-
https://github.com/MyNameIsDabin/TabbySheet
-
https://blog.naver.com/gamephysics/223825533965
-
https://github.com/NtreevSoft/Crema
- https://github.com/s2quake/crema
- https://github.com/MahApps/MahApps.Metro
- https://github.com/Actipro/WPF-Controls
- https://github.com/mmanela/diffplex
-
https://github.com/ExcelDataReader/ExcelDataReader
-
https://github.com/tonyqus/npoi
-
https://github.com/ClosedXML/ClosedXML
https://github.com/sveinungf/spreadcheetah
https://github.com/Cysharp/MasterMemory https://www.litedb.org/
https://github.com/zirplsoftware/ZCalcEngine https://github.com/pieterderycke/Jace https://github.com/soomin-kevin-sung/dotnet-calculation-engine
https://github.com/softlion/SQLite.Net-PCL2 - IBlobSerializer 지원
root/ /ByteFiles/image… /Sheets/
byte[] - byte:// - 이미지 같은거 string - text:// - 스크립트 같은거 string - base64:// string - base64url://
설정파일
- regexp _스코어시작
_스코어 시작
int / float / byte[] / DateTime
시트
주석시트
List
키prim /sub
3번째로 뒤엎는거다.
시트당 클래스/enum/const를 같이 묶으려했다
// enum
// - header: *NAME | *FIELD
// - field: *NAME | *VALUE | DESC | ATTR
// const
// - header: *NAME | *FIELD
// - field: *TYPE | *NAME | *VALUE | DESC | ATTR
// class
// - header: ?*NAME | *TYPE | PART | DESC | *TABLE
IFormulaEvaluator evaluator 검증
컴파일 Microsoft.CodeAnalysis.CSharp.Workspaces Microsoft.Build.Locator
https://learn.microsoft.com/ko-kr/nuget/consume-packages/package-references-in-project-files#controlling-dependency-assets
client/server assembly만들어서 sqlite에 삽입하니 충돌문제
- 처음에는 어셈블리 중복로드 문제인가 싶어서 살펴봤지만
- https://learn.microsoft.com/ko-kr/dotnet/standard/assembly/unloadability
- 코드를 보니 sqlite.net내부에 타입 맵핑 태이블(_mapping)이 있는데 캐슁되어 있는 부분에서 문제가 발생. 클리어 함수가 노출되어 있지않아, 리플렉션으로 강제호출
TODO
- 프로토콜 추가
- file:// file path
- proto:// json
NF.Tool.UnityCompileCache
레코드
- IL2CPP로 빌드시 clang.exe로 컴파일이 시작됨. 컴파일 캐쉬를 사용할 수 있으면 시간 절약을 할 수 있을 것임.
- 다만 유니티가 clang.exe를 실행하는데 어떻게 캐쉬 실행을 하느냐가 문제인데, wrapper에서 그냥 CreateProcess 호출하면 캐쉬가 오동작함.
- 캐쉬 실행시 lpApplicationName과 lpCommandLine을 조절 해줘야함.
dotnet으로 nativeaot로 빠르게 wrapper작성해보고 dotnet은 아무래도 용량이 크니, c/cpp 생각해봤다가 딱히 내 프로젝트고 해서 zig로 작성.
참고
- https://github.com/dotnet/runtime/blob/eeaef45074f577f35bfd1b6b02a029d4053a9683/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs#L588
- dotnet에선 Interop.Kernel32.CreateProcess시 STARTUPINFO에 null을 넘겨주는것 밖에 없음.
- lpCommandLine에서 argv[0]가 결정됨
nf.unitylibs.managers.assetbundlemanagement
nf.unitylibs.managers.patchmanagement
nf.unitylibs.managers.resourcesextra
시작하며
- puerts를 가지고 놀다가 DefaultLoader에서 파일있는지 여부를 판별하는데서 UnityEngine.Resources.Load 사용함.
- 이게 유니티가 Resources쪽 API는 놔버려서 로드를 해서 체크를 해야함.
// https://github.com/Tencent/puerts/blob/f93907e9b6110497a2fc95827851b7e05ec1e2c9/unity/Assets/core/upm/Runtime/Src/Loader.cs#L96 public bool FileExists(string filepath) bool exist = UnityEngine.Resources.Load(pathToUse) != null;
뭘할까
- Resources가 여러 제약이 있긴해도 간편함때문에 버리지는 못하고 계속 써야하는데, 중복로드 / 의존성그래프 문제
- Resources는 Assets/Resources/ => Resources.assets
- Addressable의 로컬로드는 StreamingAssets를 사용
- Assets/StreamingAssets =>StreamingAssets/
- 일단 Resources.Load 없이 존재하는지 확인가능(런타임)하는 거랑
- 정적분석으로 Resources.Load(“asdf”); // 이름 체크기능 - 코드짜면서 아날리시트 타임
- 정적 분석이라 런타임 기능 함수를 가져다 쓸 수 없음
- 정적 분석은 netpyoung/nf.unitylibs.utils를 만들면서 조금 깔딱거려봤음
삽질
- Resources.IsExist 처럼 스태틱클래스를 확장시키고 싶었으나
- 유니티는 C# 9까지 지원함.
- 스태틱 클래스 확장은 C# 14 부터 지원
- https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods#declare-extension-members | | | | ———————————————————————————————— | —————————————————————————————————————— | | AppContext.BaseDirectory; | C:\Program Files\Microsoft Visual Studio\18\Insiders\Common7\ServiceHub\Hosts\ServiceHub.Host.Extensibility.amd64\ | | typeof(ResourceLoadAnalyzer).Assembly.Location; | C:\Users\pyoung\AppData\Local\Temp\Roslyn\AnalyzerAssemblyLoader\4a41c1fd308e4a8b946ef9548f7a1c00\3\HelloHello.dll | | Assembly.GetExecutingAssembly().Location; | C:\Users\pyoung\AppData\Local\Temp\Roslyn\AnalyzerAssemblyLoader\f5def63c834c4efd803ba9f171794778\3\HelloHello.dll | | Environment.GetEnvironmentVariable(“MSBuildProjectFullPath”); | ‘’ | | Environment.GetEnvironmentVariable(“MSBuildProjectFullPath”, EnvironmentVariableTarget.Process); | ‘’ | | context.Node.SyntaxTree.FilePath; | C:\temp\unityProj\Assets\Scenes\NewMonoBehaviourScript.cs |
해킹
- importer를 만들어서 __ResourceBlabla.txt 갱신
설정은
Ref
- Runtime
- Editor
nf.unitytools.essentials
Sample.Dotnet.Nes
프로그래밍 언어관련 검색을 하다. 아 crystal언어가 지금 어떻게 되어가고 있지 생각이나서 검색중 블로그 글을 발견.
- Building Your First Emulator: Understanding how emulators work by building a NES from scratch by Matias Salles
- https://github.com/matiassalles99
- https://github.com/matiassalles99/nes-emulator-book
책을 알게 되었고 crystal언어와 SDL2로 구현되었으나, 개발 환경이 불편하고 include문을 써서 좀 코드 분석하기 불편하게 되어있어 dotnet과 SDL3 / Raylib로 구현해봄.
역시 dotnet이 visual studio가 좋아. 테스트도 잘 할 수 있고 손에 익어 바로바로 코드가 나옴. ruby가 좋아 crystal도 관심을 갖게되었는데, 책의 소스를 보다보니 점점 ruby계열 언어 아니 다른 gc언어에 대한 관심들이 떨어짐. gc언어는 그냥 dotnet 하나로 가는게 좋을듯.
그리고 다행인게 nesdev쪽 위키 가 정리가 잘 되어있어서 좋았고, 여러 youtube나 github에 참고할게 많아서 좋았음.
AMD Ryzen 7 5700g
dotnet --version 10.0.301
릴리즈는 nes기준 60프레임 맞춰서 나오는데, 디버그 빌드가 8프레임 정도밖에 안나온다. zig로 짜면 어떻게 되려나?
PPU랑 APU쪽이 빡셌음.
저 책이 아니였으면 손대볼 염두도 안났을것임. gameboy를 해볼까? 아니면 chip-8 에뮬로 가볍게 작업하고 심화로 chip-8타겟팅하는 롬을 만들 수 있도록?
일단 어찌어찌 완성시켰는데 심화해볼 수 있는것들도 남았고. 다시 관심을 가질때 다시 재미있게 가지고 놀 수 있을 프로젝트라 어느정도 1차 완성하고나서 나름 만족감을 느낄 수 있었음.
기타
구현하면서 Writing NES Emulator in Rust도 참고해서 봤는데, wiki링크가 과거 nesdev.com 기준으로 작성되었음. 사이트 분쟁이 있는지 현재는 nesdev.org로 접속이 되는데 nesdev.com 기준으로 작성된 문서/코드 주석들을 수정하는 PR을 남겼고 받아들여짐. 참고하면서 도움을 받았는데 조금이라도 도움을 줄 수 있어서 나름 만족.
Sample.Zig.Tunneler
record
zig 연습용 클론코딩. zig언어 보면서 뭔가 하나 해보고 싶었음. 스캔 돌리다가 tunneler가 기본 코드도 있고 sdl기반이라 간단해 보였음.
tunneler
- https://tunneler.org/
- by Geoffrey Silverton
- SDL Tunneler v.1.1.1 - sdl 1.2.0
- Taneli Kalvas
- https://users.jyu.fi/~tvkalvas/
- https://users.jyu.fi/~tvkalvas/code/tunneler/
- https://github.com/guyromm/tunneler
- Taneli Kalvas
- Raymond Myers tunneltanks-0.4 - sdl 1.2.10
- https://ditchers.sourceforge.net/
- https://sourceforge.net/projects/ditchers/
- https://app.zdechov.net/Tunneler/
TODO
- https://tunneler.org/overview/#more-12
press any key
shoots fired
shoots hit
percent hit (shoots hit/shoots fired)%
meters dug
meters travelled
static library?
용량이 너무 커지는데
다음으로 참고용으로 메모해둠
- https://osgameclones.com/?
- https://github.com/opengaming/osgameclones
- https://github.com/krystiankaluzny/Tanks
tetris ? - https://github.com/mmatyas/openblok
sdls - https://www.parallelrealities.co.uk/news/
-
f1spirit - https://f1spirit.jorito.net/
-
supermario - https://github.com/AnthonySturdy/SDL-Mario-Bros.
-
galaga
- https://github.com/abdullahmaswadeh/galaga
- https://github.com/frank-zago/xgalaga-sdl
-
tuxfootball - https://tuxfootball.sourceforge.net/index.php?plugin=EnticorePluginStaticContent&config=idx%3A3
-
noiz2sa
- sdl ex - https://github.com/IoriBranford/noiz2sdl2
- https://www.asahi-net.or.jp/~cs8k-cyu/windows/noiz2sa_e.html
-
road fighter
- https://github.com/reybits/road-fighter
- https://www.ugolnik.info/road-fighter/
- https://github.com/OSSGames/GAME-SDL-SPORTS-Road_Fighter_Remake
-
벽돌깨기
- https://github.com/JoshuaCrotts/Brick-Breaker
elastomania - https://github.com/elastomania/elma-classic
- xmoto
- https://github.com/xmoto/xmoto
- https://xmoto.org/
- liero
- https://www.liero.be/
- https://github.com/gliptic/liero
- https://github.com/albertz/openlierox
- gusanos
- https://github.com/wesz/gusanos
- https://www.openlierox.net/
- https://github.com/albertz/openlierox
- https://github.com/david-vanderson/dvui
raylib ?
const c = @cImport({
@cInclude("SDL3/SDL.h");
});
const std = @import("std");
pub fn main() !void {
// 1. SDL 초기화
if (!c.SDL_Init(c.SDL_INIT_VIDEO)) {
std.debug.print("SDL 초기화 실패: {s}\n", .{c.SDL_GetError()});
return error.SDLInitFailed;
}
defer c.SDL_Quit();
// 2. 기본 디스플레이 ID 가져오기 (SDL3는 ID 기반)
var count: i32 = 0;
const displays = c.SDL_GetDisplays(&count);
if (displays == null or count == 0) {
std.debug.print("디스플레이를 찾을 수 없습니다.\n", .{});
return;
}
const primary_display = displays[0];
// 3. 해당 디스플레이의 전체화면 모드 목록 가져오기
var mode_count: i32 = 0;
// SDL3에서 SDL_GetFullscreenDisplayModes는 모드 포인터 배열을 반환합니다.
const modes = c.SDL_GetFullscreenDisplayModes(primary_display, &mode_count);
if (modes == null) {
std.debug.print("모드 목록을 가져오는데 실패했습니다: {s}\n", .{c.SDL_GetError()});
return;
}
defer c.SDL_free(@ptrCast(@constCast(modes))); // SDL3에서 할당한 메모리 해제
std.debug.print("사용 가능한 모드 개수: {d}\n", .{mode_count});
std.debug.print("---------------------------------\n", .{});
// 4. 모드 순회 (Zig의 슬라이스 방식으로 접근 가능)
const modes_slice = modes[0..@intCast(mode_count)];
for (modes_slice) |mode_ptr| {
const m = mode_ptr.*; // SDL_DisplayMode 구조체 역참조
std.debug.print("{d} x {d} @ {d}Hz (픽셀 포맷: {d})\n", .{
m.w,
m.h,
@as(i32, @intFromFloat(m.refresh_rate)), // refresh_rate는 float 타입
m.format
});
}
}
http://netpyoung.github.io
- 스프링노트 - 서비스 종료
- 에버노트 - 익숙하지 않음
- 티스토리 - 커스터마이즈 불편
- 네이버 블로그 - 처음부터 고려대상 제외
그 당시 서비스가 없었음
- 노션 - 에메한 포지션
- 미디엄 - 구독유도 혐오
내용이 없는 이유
블로그 ? 개발 블로그 ? 고찰 부족. 블로그 보다 사이드프로젝트
생각중
- zig로 된 zine은 어떨까?
- 아직 성숙하지 않은거 같아 일단 보류
- https://github.com/kristoff-it/zine
어떻게 구축 시작?
jekyll => zola
- https://netpyoung.github.io/blog/netpyoung.github.io_on_jekyll/
- https://netpyoung.github.io/blog/githubpages_jekyll_v3/
- https://netpyoung.github.io/blog/jekyll_to_zola/
snippet
- 검색창 - https://www.fusejs.io/demo.html
- heyimalex/wafu- Rust port of Fuse.js
- https://github.com/netpyoung/netpyoung.github.io/commit/8902af639842a67a4656e2066dac8440ec89fc3b
- https://github.com/lispkorea/lispkorea.github.io/commit/04c68a1cb20e7e9f2902047c91bfb13d906834da
ADR
ArchitectureDecisionRecords (ADRs).
결론
컨셉자체는 괜찮은데 짜잘짜잘한거까지 하면 스트레스. 분쟁이 일어날시 팀장역활 중요.
시도
3명이서 해봤는데 adr 드라이븐을 강제해서 해봤다. 찬반으로 해서 결정하는건데 결정이 더 느리고 통과할때까지 문서만 바꾸느라 진도가 안나감.
Title: 제목
Decision: 결정
Issue:
Status: // proposed, accepted, rejected, deprecated, superseded
Expected Result: 예상결과 / Consequences 결과
버그노트
현상
추정
과정
원인
해결책
Ref:
-
https://github.blog/2020-08-13-why-write-adrs/
-
https://github.com/joelparkerhenderson/architecture-decision-record
-
템플릿
- https://github.com/joelparkerhenderson/architecture-decision-record/blob/main/templates/decision-record-template-madr/index.md
- https://github.com/joelparkerhenderson/architecture-decision-record/blob/main/templates/decision-record-template-by-michael-nygard/index.md
- init / new / add
-
예제
- https://github.com/joelparkerhenderson/architecture-decision-record/blob/main/examples/programming-languages/index.md
-
https://en.wikipedia.org/wiki/Architectural_decision
-
npryce/adr-tools - GPL
-
https://bitbucket.org/tinkerer_/adr-tools-python/src/master/
-
https://github.com/joelparkerhenderson/architecture-decision-record
변경내역을 깃 커밋 히스토리로 뽑는것에 대한.
결론
- 결론은 반대. 자동으로 뽑는건 필요하지만, 커밋 기반으로 뽑는것은 아니다.
- NF.Tool.ReleaseNoteMaker 를 쓰자
시도
- git history를 기반으로 changelog를 생성하는 것은 툴도 많고, 깃 히스토리를 파싱해서 만들면 간단하게 만들 수 있을거 같아 만들어 볼까라는 생각을 가지고 있었다.
- 주객전도
- 그렇게 몇번 코드를 가지고 놀다가. history기반으로 작업을 하면 changelog를 예쁘게 뽑기위해 커밋을 수정해야하는 경우가 생기는 경우가 생긴다.
- 불신
- 플로우에 맞추어 커밋로그를 잘 남긴다는 나 스스로 혹은 다른 넘들을 믿을 수 가 없다.
- 복잡성 증가
- 나 역시 몇번 시도 해봤는데 커밋 메시지를 changelog를 생각하면서 남긴다는것 자체가 곤욕이다.
마크업 언어
결론
markdown이 간단해서 1픽으로 하고 만약 요구사항이 늘어난다면 그 다음으로는 asciidoc을 고려.
시도
markdown, asciidoc, reStructuredText, org 들을 써봤다.
| fileextension | |
|---|---|
| markdown | .md |
| asciidoc | .adoc / .asciidoc / .asc |
| reStructuredText | .rst |
| org | .org |
복잡하고 잘 까먹는다. org는 에디터 특성을 탄다.
Ref
Serialization
-
protobuf
-
FlatBuffers
-
captin proto
-
message pack - https://github.com/Cysharp/MemoryPack
-
json
-
bson
-
BinaryPack - https://github.com/Sergio0694/BinaryPack
-
HyperSerializer - https://github.com/adam-dot-cohen/HyperSerializer
-
Apex.Serialization - https://github.com/dbolin/Apex.Serialization
-
https://docs.unity3d.com/Packages/com.unity.serialization@3.1/manual/index.html
Ref
템플릿 언어
결정
- 디버깅때문이라도 t4쓰자.
- razor는 웹전용으로만 쓰자.
시도
- mustache / handlebars 는 문법이 간단한데 이걸 기반으로 템플릿을 작성해보면 더 개판남.
- 비쥬얼스튜디오 T4 template / razor 가 디버깅이 잘됨
- t4로 작성해도
<# #>하다보면 너무 지저분해보임. 디버깅 되고 조금 더 깔끔한게 아직은 없다… - html이 아닌 문서 템플릿용도로 razor로 한번 써봤는데 t4보다 지저분해보임.
- t4로 작성해도
- liquid 개인적으로 맘에드는데 디버깅이 안되네..
task runner
결론
- just를 쓰자
- 100프로 맘에 드는건 아니지만 일단.. 뭐… 대안이 별로…
- 로직들어간건 그냥 dotnet으로
- https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app/
주저리
- https://github.com/ruby/rake
- https://github.com/pyinvoke/invoke
- https://github.com/dotnet-script/dotnet-script
rake를 전에 좋아해서 시작함. `dir`같이 명령어 바로 실행시키는 것이 맘에듬. 하지만 라이브러리 사용도 그렇고 점점 코딩하는게 불편해짐. 대중적인 pyhton으로 invoke도 써봤지만 결국엔 ruby와 마찬가지로 코딩도 불편하고 프로젝트안에 알아야 하는 언어가 하나 더 추가되는 것일 뿐. 후에 dotnet-script로 사용하다가 file-based C# apps이 가능해지고선 복잡해진 로직은 .cs로 처리하는게…
다만 dotnet쪽에 태스크 런하는게 썩 괜찮은게 없어서 테스크 러너는 아싸리 just로..
Ref
- https://github.com/bartdorlandt/Beyond_the_Makefile