চতুর্থ ব্যাচ / পঞ্চম ব্যাচ / CM সার্ভার কমান্ড —— পোর্টিং কঠিনতা গবেষণা প্রতিবেদন
গবেষণা অবজেক্ট: citymania-org/cmclient (vanilla 15.3 ব্রাঞ্চ) সোর্স কোড গভীর পাঠ গবেষণার তারিখ: 2026-08-14 সিদ্ধান্ত: তিনটি কাজের কঠিনতা ব্যাপকভাবে ভিন্ন, প্রতিটি আইটেমের মূল্যায়ন ও প্রস্তাবিত ক্রম দেওয়া হল।
এক. চতুর্থ ব্যাচ: টাউন জোনিং (growth_tiles存档 সহ)
বৈশিষ্ট্য গঠন
| উপাদান | ফাইল | আকার | ব্যাখ্যা |
|---|---|---|---|
| জোনিং মোড এনাম | cm_zoning.hpp | ৩৭ লাইন | ১২টি মূল্যায়ন মোড (CHECKOPINION/CHECKBUILD/CHECKSTACATCH/CHECKACTIVESTATIONS/CHECKBULUNSER/CHECKINDUNSER/CHECKTOWNZONES/CHECKCBACCEPTANCE/CHECKCBTOWNLIMIT/CHECKTOWNADZONES/CHECKTOWNGROWTHTILES) |
| মূল্যায়ন লজিক | cm_zoning_cmd.cpp | ৪১৩ লাইন | প্রতিটি মোডের জন্য একটি কুয়েরি ফাংশন (প্যালেট SpriteID ফেরত দেয়), TownZone/Tz ব্যাসার্ধ অ্যালগরিদম, StationFinder কভারেজ চেক, আনসার্ভিসড বিল্ডিং/ইন্ডাস্ট্রি চেক সহ |
| জোনিং টুলবার GUI | cm_zoning_gui.cpp | ২০৪ লাইন | ভিতরের/বাইরের দুটি স্তরের জোনিং মোড নির্বাচন উইন্ডো (_zoning.inner/outer গ্লোবাল স্টেট) |
| growth_tiles存档 | cm_saveload.cpp/.hpp | ৯০ লাইন | Town এক্সটেনশন ফিল্ড growth_tiles + growth_tiles_last_month (std::map<TileIndex, uint8_t>), vanilla SaveLoad হ্যান্ডলার দিয়ে存档 |
| ডেটা এক্সটেনশন | extensions/cmext_town.hpp | ~৮০ লাইন | ext::Town: growth_tiles ×2 + প্রচুর CM সার্ভার প্লে ফিল্ড (CBTownInfo কার্গো পরিসংখ্যান, বিজ্ঞাপন/তহবিল ট্র্যাকিং, hs/cs/hr শহর বৃদ্ধি গণনা) |
| মাসিক ঘূর্ণন + ট্রিগার | cm_game.cpp / town_cmd.cpp | — | NewMonth growth_tiles ঘূর্ণন; বাড়ি নির্মাণ/ভাঙা/পুনর্নির্মাণের স্থানে অবস্থা রেকর্ড |
পোর্টিং কঠিনতা প্রতি আইটেম মূল্যায়ন
| কঠিনতা | তীব্রতা | ব্যাখ্যা |
|---|---|---|
| 存档体系 পুনর্লিখন | 🟠 মাঝারি | growth_tiles vanilla DefaultSaveLoadHandler + SlSetStructListLength/SlObject ব্যবহার করে, jrpm হলো sl/ নতুন体系 (SlTableHeader/SlObjectSaveFiltered)। jrpm-এর NSL/SLE + XSLF বৈশিষ্ট্য গেট দিয়ে পুনর্লিখন করতে হবে (নতুন XSLFI_TOWN_GROWTH_TILES, সংস্করণ ১), পুরনো存档 প্রভাবিত হবে না |
| Town স্ট্রাকচার এক্সটেনশন | 🟢 কম | শুধু growth_tiles দুটি ম্যাপ নেওয়া হবে (বাদ দেওয়া CBTownInfo/বিজ্ঞাপন/তহবিল ফিল্ড——সেগুলি CM সার্ভার CityBuilder প্লে-নির্দিষ্ট); jrpm Town-এ ফিল্ড যোগ + town_sl.cpp存档 টেবিল মাউন্ট |
| মূল্যায়ন লজিক | 🟢 কম-মাঝারি | অধিকাংশই বিশুদ্ধ কুয়েরি (GetTileType/StationFinder/Town ক্যাশে/বাড়ি চেক), jrpm API বিদ্যমান; TownZone ব্যাসার্ধ অ্যালগরিদম (squared_town_zone_radius) jrpm ফিল্ড নামের সাথে মিলাতে হবে |
| রেন্ডার পাইপলাইন | 🟠 মাঝারি-উচ্চ | DrawTileZoning ভিউপোর্ট ড্র পাইপলাইনে সংযুক্ত করতে হবে——তৃতীয় ব্যাচ হাইলাইটের সাথে TileHighlight রেন্ডার মেকানিজম শেয়ার করে। হাইলাইট পাইপলাইন না থাকলে আলাদাভাবে তৈরি করতে হবে (পরামর্শ: প্রথমে হাইলাইট, তারপর জোনিং) |
| স্প্রাইট রিসোর্স | 🟠 মাঝারি | ১২টি প্যালেট CM_SPR_PALETTE_ZONING_* কাস্টম স্প্রাইট ব্যবহার করে, jrpm-এ নেই → বিদ্যমান প্যালেট স্প্রাইট দিয়ে প্রতিস্থাপন বা নতুন রিসোর্স যোগ করতে হবে |
| ইভেন্ট হুক | 🟠 মাঝারি | growth_tiles রেকর্ড cmclient-এর ইভেন্ট বাস-এর উপর নির্ভরশীল (event::HouseBuilt/HouseCleared/..., cm_main.cpp-এর Emit)। jrpm-এ এই মেকানিজম নেই → সরাসরি town_cmd.cpp-তে বাড়ি নির্মাণ/ভাঙার স্থানে হুক যোগ + NewMonth ঘূর্ণন (IntervalTimer) |
কঠিনতা সিদ্ধান্ত: 🟠 মাঝারি-উচ্চ (প্রায় ১.৫–২ রাউন্ড বিশেষ কাজ, প্রতি রাউন্ড ৪–৬ ঘন্টা)
- পূর্বশর্ত: দৃঢ়ভাবে পরামর্শ দেওয়া হয় তৃতীয় ব্যাচ হাইলাইট সিস্টেম শেষ করার পর করা (রেন্ডার পাইপলাইন শেয়ারিং)
- যদি শুধু "১২টি জোনিং রঙিনকরণ, growth_tiles存档 ছাড়া" করা হয়: কঠিনতা 🟡 মাঝারিতে নেমে আসে (存档 এক্সটেনশন বাদ, প্রায় ১ রাউন্ড)
দুই. পঞ্চম ব্যাচ: কমান্ড রিপ্লে + এক্সপোর্ট/রেকর্ডিং
২.১ কমান্ড রিপ্লে (cm_command_log + cm_commands + generated)
| উপাদান | আকার | ব্যাখ্যা |
|---|---|---|
| কমান্ড অবজেক্ট লেয়ার | cm_command_type.hpp + generated/cm_gen_commands (২২৫১+১৪১৮ লাইন) | প্রতিটি vanilla কমান্ড প্রোগ্রামেবল অবজেক্টে র্যাপ করা (as_company/with_callback/set_auto), কমান্ড→বিটস্ট্রিম সিরিয়ালাইজেশন সহ |
| কমান্ড লগ লোড | cm_command_log.cpp (২০৩ লাইন) | lzma ডিকম্প্রেশন + BitOStream বিটস্ট্রিম পার্স → _fake_commands কিউ (টিক কাউন্টার/প্রত্যাশিত ফলাফল/র্যান্ডম সীড/CommandPacket) |
| কমান্ড নির্বাহ | ExecuteFakeCommands | টিক কাউন্টার ক্রম অনুযায়ী নির্বাহ: ExecuteCommand(&cp) (vanilla অভ্যন্তরীণ API) + র্যান্ডম সীড/ফলাফল যাচাই (প্রতারণা-বিরোধী), মাল্টিপ্লেয়ারে সব ক্লায়েন্টে ফরোয়ার্ড |
মূল পার্থক্য (কঠিনতা নির্ধারণ করে):
| cmclient | jrpm | প্রভাব |
|---|---|---|
ExecuteCommand(CommandPacket*) | এই ফাংশন নেই, কমান্ড মূল হলো DoCommandPInternal(Commands, TileIndex, CommandPayloadBase&, ...) | CommandPacket → DoCommandPInternal পেলোড রূপান্তর স্তর লিখতে হবে 🟠 |
| CommandPacket ফিল্ড (vanilla) | CommandPacket বিদ্যমান কিন্তু গঠন ভিন্ন (GeneralCommandPacket<DynBaseCommandContainer>) | ফিল্ড ম্যাপিং অভিযোজন করতে হবে 🟠 |
GetCommandName | ✅ বিদ্যমান (command_func.h:166) | 🟢 |
outgoing_queue (মাল্টিপ্লেয়ার ফরোয়ার্ড) | jrpm নেটওয়ার্ক স্তর ভিন্ন (OutgoingCommandPacket/ServerNetworkGameSocketHandler::SendCommand) | মাল্টিপ্লেয়ার রিপ্লের জন্য ফরোয়ার্ড লজিক পুনর্লিখন প্রয়োজন 🟠 |
| রেকর্ডার (কিভাবে .cmd ফাইল জেনারেট হয়) | cmclient-এর রেকর্ডিং হুক কমান্ড অবজেক্ট লেয়ারের post() ইন্টারসেপ্টের উপর নির্ভরশীল | jrpm কমান্ড টেমপ্লেটাইজড Post → কমান্ড ডিসপ্যাচ পয়েন্টে রেকর্ডিং হুক যোগ করতে হবে 🔴 মূল কাজ |
| ফাইল ফরম্যাট | প্রাইভেট (vanilla কমান্ড ID + বিটস্ট্রিম) | jrpm কমান্ড ID vanilla থেকে সম্পূর্ণ ভিন্ন → রিপ্লে ফাইল সামঞ্জস্যপূর্ণ নয়, ফরম্যাট পুনরায় ডিজাইন করতে হবে 🟠 |
২.২ এক্সপোর্ট / রেকর্ডিং (cm_export.cpp, ৫৩৬ লাইন)
| বৈশিষ্ট্য | ব্যাখ্যা | কঠিনতা |
|---|---|---|
| ExportOpenttdData | JSON এক্সপোর্ট বাড়ির স্পেক/কার্গো স্পেক/প্যালেট/ইঞ্জিন তথ্য (JsonWriter) | 🟢 কম-মাঝারি (স্বাধীন, Spec স্ট্রাকচার পড়ে JSON লেখা) |
| ViewportExport / ExportFrameSprites | প্রতি ফ্রেম ভিউপোর্ট স্প্রাইট এক্সপোর্ট (ভিউপোর্ট অভ্যন্তরীণ ড্র ভেক্টর TileSpriteToDrawVector/ParentSpriteToSortVector-এর উপর নির্ভরশীল) | 🟠 মাঝারি-উচ্চ (jgrpp ভিউপোর্ট পাইপলাইন ভিন্ন, ভেক্টর ইন্টারফেস সারিবদ্ধ করতে হবে) |
কঠিনতা সিদ্ধান্ত: 🟠 মাঝারি-উচ্চ (প্রায় ২ রাউন্ড বিশেষ কাজ)
- কমান্ড রিপ্লে সবচেয়ে বড় অংশ: মূল কাজ = ①কমান্ড ডিসপ্যাচ পয়েন্টে রেকর্ডিং হুক যোগ (jrpm টেমপ্লেটাইজড কমান্ড সিস্টেমের অভিযোজন) ②CommandPacket → DoCommandPInternal নির্বাহ স্তর ③নতুন ফাইল ফরম্যাট ডিজাইন। প্রথমে কমান্ড অবজেক্ট লেয়ার পোর্ট করার পরামর্শ দেওয়া হচ্ছে (তৃতীয় ব্যাচ ব্লুপ্রিন্টের ভিত্তি, এছাড়াও রিপ্লের ভিত্তি)
- এক্সপোর্ট: JSON ডেটা এক্সপোর্ট স্বাধীনভাবে আগে করা যেতে পারে (কম-মাঝারি); ফ্রেম রেকর্ডিং ভিউপোর্ট সারিবদ্ধকরণের উপর নির্ভরশীল (হাইলাইটের সাথে একই ব্যাচে প্রক্রিয়া)
তিন. CM সার্ভার কমান্ড (cm_console_cmds.cpp, ২৮৯ লাইন)
কমান্ড তালিকা ও প্রতি আইটেম কঠিনতা
| কমান্ড | বৈশিষ্ট্য | jrpm-এর জন্য কঠিনতা | মন্তব্য |
|---|---|---|---|
cmgamespeed [n] | গেম গতি পরিবর্তন | 🟢 অত্যন্ত কম (~২০ লাইন) | jrpm-এ ইতিমধ্যে _game_speed গ্লোবাল আছে (gfx.cpp:52), শুধু কমান্ড শেলের অভাব |
cmstep [n] | n টিক ধাপ | ⏭️ jrpm-এ ইতিমধ্যে আছে | step কমান্ড (ConStepGame) ফাংশন একই, বাদ দিন |
cmexport | openttd.json এক্সপোর্ট | 🟢 কম-মাঝারি | ExportOpenttdData-র উপর নির্ভরশীল (পঞ্চম ব্যাচ দেখুন) |
cmtreemap <file> | উচ্চতা ম্যাপ গাছ লাগানো | 🟡 মাঝারি | উচ্চতা ম্যাপ পড়া + গাছ লাগানোর কমান্ড, স্বাধীন |
cmreset_town_growth | শহর বৃদ্ধি রেকর্ড মুছে ফেলা | 🟢 কম | টাউন জোনিং ফিল্ডের উপর নির্ভরশীল |
cmload_commands | কমান্ড রিপ্লে লোড | 🟠 মাঝারি-উচ্চ | কমান্ড রিপ্লে পরিকাঠামোর উপর নির্ভরশীল |
cmstart_record / cmstop_record | ফ্রেম রেকর্ডিং | 🟠 মাঝারি-উচ্চ | রেকর্ডিং পরিকাঠামোর উপর নির্ভরশীল |
cmgamestats | গেম সেশন পরিসংখ্যান | 🟢 কম | স্বাধীন |
cmgfxdebug | গ্রাফিক্স ডিবাগ | 🟢 কম | স্বাধীন |
কঠিনতা সিদ্ধান্ত: 🟢 সামগ্রিকভাবে কম (প্রতি কমান্ড ০.৫–২ ঘন্টা)
প্রস্তাবিত ক্রম: cmgamespeed (১০ মিনিট) → cmgamestats/cmgfxdebug (প্রায় ~১ ঘন্টা) → cmexport (পঞ্চম ব্যাচ এক্সপোর্টের সাথে) → cmtreemap (~২ ঘন্টা) → cmreset_town_growth (চতুর্থ ব্যাচের সাথে) → cmload_commands/cmstart_record (পঞ্চম ব্যাচ রিপ্লে/রেকর্ডিংয়ের সাথে)।
চার. সামগ্রিক প্রস্তাবিত রুট
① হাইলাইট সিস্টেম (তৃতীয় ব্যাচ মূল, ~২-৩ রাউন্ড) ← ব্লুপ্রিন্ট/জোনিংয়ের রেন্ডার ভিত্তি
② কমান্ড অবজেক্ট লেয়ার (তৃতীয় ব্যাচ ব্লুপ্রিন্ট + পঞ্চম ব্যাচ রিপ্লের ভিত্তি, ~১-২ রাউন্ড)
③ ব্লুপ্রিন্ট (~১ রাউন্ড)
④ টাউন জোনিং (~১.৫ রাউন্ড, ① রেন্ডার পাইপলাইনের উপর নির্ভরশীল; growth_tiles XSLF গেটেড)
⑤ কমান্ড রিপ্লে + এক্সপোর্ট (~২ রাউন্ড, ②-র উপর নির্ভরশীল; JSON এক্সপোর্ট আগে স্বাধীনভাবে করা যেতে পারে)
⑥ CM সার্ভার কমান্ড (বিভিন্ন ব্যাচের মধ্যে বিক্ষিপ্তভাবে সন্নিবেশ, gamespeed/step এখনই করা যেতে পারে)পাঁচ. এখনই কম খরচে বাস্তবায়নযোগ্য আইটেম (কোনো বড় প্রকৌশলের উপর নির্ভরশীল নয়)
১. cmgamespeed কমান্ড (~২০ লাইন, _game_speed পরিবর্তন) ২. step ইতিমধ্যে আছে → করার প্রয়োজন নেই ৩. cmgamestats / cmgfxdebug (প্রায় ~১ ঘন্টা, স্বাধীন) ৪. cmexport-এর JSON ডেটা এক্সপোর্ট (~২ ঘন্টা, স্বাধীন) ৫. cmtreemap (~২ ঘন্টা, স্বাধীন)
এই ৫টি আইটেম প্রায় অর্ধেক দিনের কাজ, "শূন্য ব্যাচ" হিসেবে আগে বাস্তবায়ন করা যেতে পারে, তৃতীয়/চতুর্থ/পঞ্চম ব্যাচের সাথে সমান্তরালে কোনো বিরোধ নেই।