mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-23 20:09:46 +03:00
Add Direct Connect Button and Screen (#30)
* Add Direct Connect Button and Screen * Remove accidental extra build directories for wasm * Add DirectConnectScreen.cpp to the CMake * Use Hungarian coding style notation
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -382,4 +382,4 @@ FodyWeavers.xsd
|
||||
|
||||
/wasm
|
||||
|
||||
/assets/
|
||||
/assets/
|
||||
@@ -56,6 +56,7 @@ add_library(reminecraftpe-core STATIC
|
||||
client/gui/screens/OptionsScreen.cpp
|
||||
client/gui/screens/StartMenuScreen.cpp
|
||||
client/gui/screens/CreateWorldScreen.cpp
|
||||
client/gui/screens/DirectConnectScreen.cpp
|
||||
client/gui/screens/SelectWorldScreen.cpp
|
||||
client/gui/screens/SavingWorldScreen.cpp
|
||||
client/gui/screens/InvalidLicenseScreen.cpp
|
||||
|
||||
@@ -8,30 +8,30 @@
|
||||
|
||||
#include "Button.hpp"
|
||||
|
||||
Button::Button(int a2, int xPos, int yPos, int btnWidth, int btnHeight, const std::string& text)
|
||||
Button::Button(int buttonId, int xPos, int yPos, int btnWidth, int btnHeight, const std::string& text)
|
||||
{
|
||||
field_30 = a2;
|
||||
m_buttonId = buttonId;
|
||||
m_xPos = xPos;
|
||||
m_yPos = yPos;
|
||||
field_18 = text;
|
||||
m_text = text;
|
||||
m_width = btnWidth;
|
||||
m_height = btnHeight;
|
||||
}
|
||||
|
||||
Button::Button(int a2, int xPos, int yPos, const std::string& text)
|
||||
Button::Button(int buttonId, int xPos, int yPos, const std::string& text)
|
||||
{
|
||||
field_30 = a2;
|
||||
m_buttonId = buttonId;
|
||||
m_xPos = xPos;
|
||||
m_yPos = yPos;
|
||||
field_18 = text;
|
||||
m_text = text;
|
||||
m_width = 200;
|
||||
m_height = 24;
|
||||
}
|
||||
|
||||
Button::Button(int a2, const std::string& text)
|
||||
Button::Button(int buttonId, const std::string& text)
|
||||
{
|
||||
field_30 = a2;
|
||||
field_18 = text;
|
||||
m_buttonId = buttonId;
|
||||
m_text = text;
|
||||
m_width = 200;
|
||||
m_height = 24;
|
||||
}
|
||||
@@ -93,5 +93,5 @@ void Button::render(Minecraft* pMinecraft, int xPos, int yPos)
|
||||
else
|
||||
textColor = int(0xE0E0E0U);
|
||||
|
||||
drawCenteredString(pFont, field_18, m_xPos + m_width / 2, m_yPos + (m_height - 8) / 2, textColor);
|
||||
drawCenteredString(pFont, m_text, m_xPos + m_width / 2, m_yPos + (m_height - 8) / 2, textColor);
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ public:
|
||||
int m_height = 0;
|
||||
int m_xPos = 0;
|
||||
int m_yPos = 0;
|
||||
std::string field_18 = "";
|
||||
int field_30;
|
||||
std::string m_text = "";
|
||||
int m_buttonId;
|
||||
bool m_bEnabled = true;
|
||||
bool m_bVisible = true;
|
||||
bool field_36 = false;
|
||||
|
||||
@@ -262,13 +262,13 @@ void TextInputBox::render()
|
||||
int textYPos = (m_height - 8) / 2;
|
||||
|
||||
if (m_text.empty())
|
||||
drawString(m_pFont, m_placeholder, m_xPos + 2, m_yPos + 2, 0x404040);
|
||||
drawString(m_pFont, m_placeholder, m_xPos + 5, m_yPos + textYPos, 0x404040);
|
||||
else
|
||||
drawString(m_pFont, m_text, m_xPos + 2, m_yPos + textYPos, 0xFFFFFF);
|
||||
drawString(m_pFont, m_text, m_xPos + 5, m_yPos + textYPos, 0xFFFFFF);
|
||||
|
||||
if (m_bCursorOn)
|
||||
{
|
||||
int xPos = 2;
|
||||
int xPos = 5;
|
||||
|
||||
std::string substr = m_text.substr(0, m_insertHead);
|
||||
xPos += m_pFont->width(substr);
|
||||
|
||||
@@ -32,7 +32,7 @@ ConfirmScreen::ConfirmScreen(Screen* pScreen, const std::string& line1, const st
|
||||
|
||||
void ConfirmScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
postResult(pButton->field_30 == 0);
|
||||
postResult(pButton->buttonId == 0);
|
||||
}
|
||||
|
||||
bool ConfirmScreen::handleBackEvent(bool b)
|
||||
|
||||
@@ -68,12 +68,12 @@ static std::string GetUniqueLevelName(LevelStorageSource* pSource, const std::st
|
||||
|
||||
void CreateWorldScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnBack.field_30)
|
||||
if (pButton->buttonId == m_btnBack.buttonId)
|
||||
{
|
||||
m_pMinecraft->setScreen(new SelectWorldScreen);
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnCreate.field_30)
|
||||
if (pButton->buttonId == m_btnCreate.buttonId)
|
||||
{
|
||||
std::string nameStr = m_textName.m_text;
|
||||
std::string seedStr = m_textSeed.m_text;
|
||||
|
||||
83
source/client/gui/screens/DirectConnectScreen.cpp
Normal file
83
source/client/gui/screens/DirectConnectScreen.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "DirectConnectScreen.hpp"
|
||||
#include "ProgressScreen.hpp"
|
||||
#include "JoinGameScreen.hpp"
|
||||
#include "client/common/Util.hpp"
|
||||
|
||||
DirectConnectScreen::DirectConnectScreen() :
|
||||
m_textAddress(1, 0, 0, 0, 0, "Server address"),
|
||||
m_btnJoin(2, "Join Game"),
|
||||
m_btnQuit(3, "Cancel")
|
||||
{}
|
||||
|
||||
void DirectConnectScreen::init()
|
||||
{
|
||||
const int CONTAINER_PADDING = 5;
|
||||
const int BUTTON_CONTAINER_PADDING = 5;
|
||||
const int BUTTON_CONTAINER_WIDTH = 200;
|
||||
|
||||
m_textAddress.m_width = 200;
|
||||
m_textAddress.m_height = 20;
|
||||
|
||||
m_btnJoin.m_width = (BUTTON_CONTAINER_WIDTH / 2) - (BUTTON_CONTAINER_PADDING / 2);
|
||||
m_btnJoin.m_height = 20;
|
||||
|
||||
m_btnQuit.m_width = (BUTTON_CONTAINER_WIDTH / 2) - (BUTTON_CONTAINER_PADDING / 2);
|
||||
m_btnQuit.m_height = 20;
|
||||
|
||||
m_textAddress.m_xPos = (m_width / 2) - (m_textAddress.m_width / 2);
|
||||
m_textAddress.m_yPos = (m_height / 2) - m_btnJoin.m_height - CONTAINER_PADDING;
|
||||
|
||||
m_btnJoin.m_xPos = (m_width / 2) - (m_btnJoin.m_width) - (BUTTON_CONTAINER_PADDING / 2);
|
||||
m_btnJoin.m_yPos = (m_height / 2) + CONTAINER_PADDING + m_textAddress.m_height;
|
||||
|
||||
m_btnQuit.m_xPos = (m_width / 2) + (BUTTON_CONTAINER_PADDING / 2);
|
||||
m_btnQuit.m_yPos = (m_height / 2) + CONTAINER_PADDING + m_textAddress.m_height;
|
||||
|
||||
m_textInputs.push_back(&m_textAddress);
|
||||
m_buttons.push_back(&m_btnQuit);
|
||||
m_buttons.push_back(&m_btnJoin);
|
||||
|
||||
m_textAddress.init(m_pFont);
|
||||
}
|
||||
|
||||
void DirectConnectScreen::render(int x, int y, float f)
|
||||
{
|
||||
renderBackground();
|
||||
Screen::render(x, y, f);
|
||||
|
||||
drawCenteredString(m_pFont, "Direct Connect", m_width / 2, 30, 0xFFFFFF);
|
||||
drawString(m_pFont, "Server address", m_textAddress.m_xPos, m_textAddress.m_yPos - 10, 0xDDDDDD);
|
||||
}
|
||||
|
||||
void DirectConnectScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->buttonId == m_btnJoin.buttonId)
|
||||
{
|
||||
if (!m_textAddress.m_text.empty())
|
||||
{
|
||||
PingedCompatibleServer newPgs;
|
||||
RakNet::SystemAddress sysAddress;
|
||||
|
||||
sysAddress.FromString(m_textAddress.m_text.c_str());
|
||||
newPgs.m_address = sysAddress;
|
||||
|
||||
m_pMinecraft->joinMultiplayer(newPgs);
|
||||
m_pMinecraft->setScreen(new ProgressScreen);
|
||||
|
||||
m_btnJoin.m_bEnabled = false;
|
||||
m_textAddress.m_bEnabled = false;
|
||||
}
|
||||
}
|
||||
else if (pButton->buttonId == m_btnQuit.buttonId)
|
||||
{
|
||||
m_pMinecraft->setScreen(new JoinGameScreen);
|
||||
}
|
||||
}
|
||||
26
source/client/gui/screens/DirectConnectScreen.hpp
Normal file
26
source/client/gui/screens/DirectConnectScreen.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Screen.hpp"
|
||||
|
||||
class DirectConnectScreen : public Screen
|
||||
{
|
||||
public:
|
||||
DirectConnectScreen();
|
||||
|
||||
virtual void init() override;
|
||||
virtual void buttonClicked(Button* pButton) override;
|
||||
virtual void render(int x, int y, float f) override;
|
||||
|
||||
private:
|
||||
TextInputBox m_textAddress;
|
||||
Button m_btnQuit;
|
||||
Button m_btnJoin;
|
||||
};
|
||||
@@ -20,12 +20,12 @@ InvalidLicenseScreen::InvalidLicenseScreen(int error, bool bHasQuitButton) :
|
||||
|
||||
void InvalidLicenseScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnOk.field_30)
|
||||
if (pButton->buttonId == m_btnOk.buttonId)
|
||||
{
|
||||
m_pMinecraft->quit();
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnBuy.field_30)
|
||||
if (pButton->buttonId == m_btnBuy.buttonId)
|
||||
{
|
||||
m_pMinecraft->platform()->buyGame();
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
********************************************************************/
|
||||
|
||||
#include "JoinGameScreen.hpp"
|
||||
#include "DirectConnectScreen.hpp"
|
||||
#include "ProgressScreen.hpp"
|
||||
#include "StartMenuScreen.hpp"
|
||||
|
||||
JoinGameScreen::JoinGameScreen() :
|
||||
m_btnJoin(2, "Join Game"),
|
||||
m_btnBack(3, "Back")
|
||||
m_btnDirectConnect(3, "Direct Connect"),
|
||||
m_btnBack(4, "Back")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,7 +26,7 @@ JoinGameScreen::~JoinGameScreen()
|
||||
|
||||
void JoinGameScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnJoin.field_30)
|
||||
if (pButton->buttonId == m_btnJoin.buttonId)
|
||||
{
|
||||
if (isIndexValid(m_pAvailableGamesList->m_selectedIndex))
|
||||
{
|
||||
@@ -32,11 +34,17 @@ void JoinGameScreen::buttonClicked(Button* pButton)
|
||||
m_pMinecraft->setScreen(new ProgressScreen);
|
||||
|
||||
m_btnJoin.m_bEnabled = false;
|
||||
m_btnDirectConnect.m_bEnabled = false;
|
||||
m_btnBack.m_bEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnBack.field_30)
|
||||
if (pButton->buttonId == m_btnDirectConnect.buttonId)
|
||||
{
|
||||
m_pMinecraft->setScreen(new DirectConnectScreen);
|
||||
}
|
||||
|
||||
if (pButton->buttonId == m_btnBack.buttonId)
|
||||
{
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
}
|
||||
@@ -55,13 +63,19 @@ bool JoinGameScreen::handleBackEvent(bool b)
|
||||
|
||||
void JoinGameScreen::init()
|
||||
{
|
||||
m_btnBack.m_yPos = m_btnJoin.m_yPos = m_height - 26;
|
||||
m_btnBack.m_width = m_btnJoin.m_width = 120;
|
||||
const int BUTTON_WIDTH = 120;
|
||||
|
||||
m_btnJoin.m_xPos = m_width / 2 - 124;
|
||||
m_btnBack.m_xPos = m_width / 2 + 4;
|
||||
m_btnBack.m_yPos = m_btnJoin.m_yPos = m_btnDirectConnect.m_yPos = m_height - 27;
|
||||
m_btnBack.m_width = m_btnJoin.m_width = BUTTON_WIDTH;
|
||||
|
||||
m_btnJoin.m_xPos = m_width / 2 - (BUTTON_WIDTH + (BUTTON_WIDTH / 2)) - 4;
|
||||
m_btnDirectConnect.m_xPos = (m_width / 2) - (BUTTON_WIDTH / 2);
|
||||
m_btnBack.m_xPos = m_width / 2 + 4 + (BUTTON_WIDTH / 2);
|
||||
|
||||
m_btnDirectConnect.m_width = 120;
|
||||
|
||||
m_buttons.push_back(&m_btnJoin);
|
||||
m_buttons.push_back(&m_btnDirectConnect);
|
||||
m_buttons.push_back(&m_btnBack);
|
||||
|
||||
m_pMinecraft->m_pRakNetInstance->clearServerList();
|
||||
@@ -69,6 +83,7 @@ void JoinGameScreen::init()
|
||||
m_pAvailableGamesList = new AvailableGamesList(m_pMinecraft, m_width, m_height, 24, m_height - 30, 28);
|
||||
|
||||
m_buttonTabList.push_back(&m_btnJoin);
|
||||
m_buttonTabList.push_back(&m_btnDirectConnect);
|
||||
m_buttonTabList.push_back(&m_btnBack);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
|
||||
public:
|
||||
Button m_btnJoin;
|
||||
Button m_btnDirectConnect;
|
||||
Button m_btnBack;
|
||||
AvailableGamesList* m_pAvailableGamesList = nullptr;
|
||||
};
|
||||
|
||||
@@ -161,7 +161,7 @@ void OptionsScreen::buttonClicked(Button* pButton)
|
||||
Options& o = m_pMinecraft->m_options;
|
||||
|
||||
bool* pOption = nullptr;
|
||||
switch (pButton->field_30)
|
||||
switch (pButton->buttonId)
|
||||
{
|
||||
case OB_BACK:
|
||||
if (m_pMinecraft->isLevelGenerated())
|
||||
|
||||
@@ -100,16 +100,16 @@ void PauseScreen::render(int a, int b, float c)
|
||||
|
||||
void PauseScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnBack.field_30)
|
||||
if (pButton->buttonId == m_btnBack.buttonId)
|
||||
m_pMinecraft->setScreen(nullptr);
|
||||
|
||||
if (pButton->field_30 == m_btnQuit.field_30)
|
||||
if (pButton->buttonId == m_btnQuit.buttonId)
|
||||
m_pMinecraft->leaveGame(false);
|
||||
|
||||
if (pButton->field_30 == m_btnQuitAndCopy.field_30)
|
||||
if (pButton->buttonId == m_btnQuitAndCopy.buttonId)
|
||||
m_pMinecraft->leaveGame(true);
|
||||
|
||||
if (pButton->field_30 == m_btnVisible.field_30)
|
||||
if (pButton->buttonId == m_btnVisible.buttonId)
|
||||
{
|
||||
if (m_pMinecraft->m_pRakNetInstance && m_pMinecraft->m_pRakNetInstance->m_bIsHost)
|
||||
{
|
||||
@@ -121,7 +121,7 @@ void PauseScreen::buttonClicked(Button* pButton)
|
||||
}
|
||||
|
||||
#ifdef ENH_ADD_OPTIONS_PAUSE
|
||||
if (pButton->field_30 == m_btnOptions.field_30)
|
||||
if (pButton->buttonId == m_btnOptions.buttonId)
|
||||
m_pMinecraft->setScreen(new OptionsScreen);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ bool SelectWorldScreen::handleBackEvent(bool b)
|
||||
|
||||
void SelectWorldScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnCreateNew.field_30)
|
||||
if (pButton->buttonId == m_btnCreateNew.buttonId)
|
||||
{
|
||||
#ifndef ORIGINAL_CODE
|
||||
m_pMinecraft->setScreen(new CreateWorldScreen);
|
||||
@@ -199,19 +199,19 @@ void SelectWorldScreen::buttonClicked(Button* pButton)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnDelete.field_30)
|
||||
if (pButton->buttonId == m_btnDelete.buttonId)
|
||||
{
|
||||
LevelSummary ls(m_pWorldSelectionList->m_items[m_pWorldSelectionList->m_selectedIndex]);
|
||||
m_pMinecraft->setScreen(new DeleteWorldScreen(ls));
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnBack.field_30)
|
||||
if (pButton->buttonId == m_btnBack.buttonId)
|
||||
{
|
||||
// @TODO: m_pMinecraft->cancelLocateMultiplayer();
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnUnknown.field_30)
|
||||
if (pButton->buttonId == m_btnUnknown.buttonId)
|
||||
{
|
||||
m_pWorldSelectionList->selectItem(m_pWorldSelectionList->getItemAtPosition(m_width / 2, m_height / 2), false);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ void StartMenuScreen::_updateLicense()
|
||||
|
||||
void StartMenuScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_startButton.field_30)
|
||||
if (pButton->buttonId == m_startButton.buttonId)
|
||||
{
|
||||
#if defined(DEMO)
|
||||
m_pMinecraft->selectLevel("_DemoLevel", "_DemoLevel", int(getEpochTimeS()));
|
||||
@@ -64,12 +64,12 @@ void StartMenuScreen::buttonClicked(Button* pButton)
|
||||
m_pMinecraft->setScreen(new SelectWorldScreen);
|
||||
#endif
|
||||
}
|
||||
else if (pButton->field_30 == m_joinButton.field_30)
|
||||
else if (pButton->buttonId == m_joinButton.buttonId)
|
||||
{
|
||||
m_pMinecraft->locateMultiplayer();
|
||||
m_pMinecraft->setScreen(new JoinGameScreen);
|
||||
}
|
||||
else if (pButton->field_30 == m_buyButton.field_30)
|
||||
else if (pButton->buttonId == m_buyButton.buttonId)
|
||||
{
|
||||
#if !defined(DEMO) && defined(CAN_QUIT)
|
||||
m_pMinecraft->quit();
|
||||
@@ -77,7 +77,7 @@ void StartMenuScreen::buttonClicked(Button* pButton)
|
||||
m_pMinecraft->platform()->buyGame();
|
||||
#endif
|
||||
}
|
||||
else if (pButton->field_30 == m_optionsButton.field_30)
|
||||
else if (pButton->buttonId == m_optionsButton.buttonId)
|
||||
{
|
||||
m_pMinecraft->setScreen(new OptionsScreen);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
<ClInclude Include="..\source\client\gui\screens\ConfirmScreen.hpp" />
|
||||
<ClInclude Include="..\source\client\gui\screens\CreateWorldScreen.hpp" />
|
||||
<ClInclude Include="..\source\client\gui\screens\DeleteWorldScreen.hpp" />
|
||||
<ClInclude Include="..\source\client\gui\screens\DirectConnectScreen.hpp" />
|
||||
<ClInclude Include="..\source\client\gui\screens\IngameBlockSelectionScreen.hpp" />
|
||||
<ClInclude Include="..\source\client\gui\screens\InvalidLicenseScreen.hpp" />
|
||||
<ClInclude Include="..\source\client\gui\screens\JoinGameScreen.hpp" />
|
||||
@@ -360,6 +361,7 @@
|
||||
<ClCompile Include="..\source\client\gui\screens\ConfirmScreen.cpp" />
|
||||
<ClCompile Include="..\source\client\gui\screens\CreateWorldScreen.cpp" />
|
||||
<ClCompile Include="..\source\client\gui\screens\DeleteWorldScreen.cpp" />
|
||||
<ClCompile Include="..\source\client\gui\screens\DirectConnectScreen.cpp" />
|
||||
<ClCompile Include="..\source\client\gui\screens\IngameBlockSelectionScreen.cpp" />
|
||||
<ClCompile Include="..\source\client\gui\screens\InvalidLicenseScreen.cpp" />
|
||||
<ClCompile Include="..\source\client\gui\screens\JoinGameScreen.cpp" />
|
||||
|
||||
@@ -660,6 +660,9 @@
|
||||
<ClInclude Include="..\source\client\gui\screens\DeleteWorldScreen.hpp">
|
||||
<Filter>source\client\gui\screens</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\source\client\gui\screens\DirectConnectScreen.hpp">
|
||||
<Filter>source\client\gui\screens</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\source\client\gui\screens\IngameBlockSelectionScreen.hpp">
|
||||
<Filter>source\client\gui\screens</Filter>
|
||||
</ClInclude>
|
||||
@@ -1415,6 +1418,9 @@
|
||||
<ClCompile Include="..\source\client\gui\screens\DeleteWorldScreen.cpp">
|
||||
<Filter>source\client\gui\screens</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\client\gui\screens\DirectConnectScreen.cpp">
|
||||
<Filter>source\client\gui\screens</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\client\gui\screens\IngameBlockSelectionScreen.cpp">
|
||||
<Filter>source\client\gui\screens</Filter>
|
||||
</ClCompile>
|
||||
|
||||
Reference in New Issue
Block a user