알라딘MGG와이드바


Ubuntu 20.04 LTS 에 Docker 로 모니위키(moniwiki) 설치하기 개발 이야기

귀찮으면 그냥 도커로 컨테이너 올리면 된다.

docker run -d --name docker_moniwiki -p 9452:80 ziozzang/moniwiki

# docker ps
ziozzang/moniwiki "/bin/sh -c 'bash -c…" 0.0.0.0:9452->80/tcp, :::9452->80/tcp   docker_moniwiki

http://localhost:9452/ 으로 접속해서 '모니위키로 오신 것을 환영합니다 ! 처음 설치 하시는군요' 가 나오는 걸 확인한다.
설정값을 변경하려면 docker 컨테이너로 들어간다.

$ docker exec -i -t docker_moniwiki /bin/bash
# cd /var/www/html/
$ sh monisetup.sh 실행한 뒤 브라우저에서 monisetup.php 를 연다.
 $ sh monisetup.sh 를 실행했을 때 Please enter the Apache user ID (e.g. nobody): 와 Please enter the Apache group ID (e.g. nobody): 를 묻는데 그냥 root 혹은 root 권한이 있는 유저 아이디를 입력하면 퉁과한다. -> 이건 왜 이렇게 해야 하는지 모르겠다.

데이터 백업이나 마이그레이션을 위해 -v 나 --mount 으로 마운드 혹은 도커 볼륨을 지정해 주면 더 좋을 거 같다.

아쉬운 것은 저 도커 이미지에서도 LaTeX 는 동작하지 않는다는 거.
모니위키에서 LaTeX 쓸려면 어떻게 해야 하나...

Ubuntu 20.04 LTS 에 모니위키(moniwiki) 설치하기 개발 이야기

Ubuntu 20.04 LTS 에 모니위키(moniwiki) 설치하기

이제 moniwiki 떠나보내줘야 할 때가 아닌가 싶으면서도, 손에 익은 도구라 버리질 못한다.(누가 maintenance 좀... T_T)
이번에 Ubuntu 20.04 LTS 를 새로 설치하면서, 클린 상태에서 모니위키를 설치하는 과정을 정리한다.

apache2 부터 설치
$ sudo apt-get update
$ sudo apt-get install apache2
http://127.0.0.1 에 Apache2 Ubuntu Default Page 가 보이면 성공

Php5.6 설치
Step 1 – Add PHP PPA
$ sudo apt install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt update
Step 2 – Install Required PHP Version
$ sudo apt install -y php5.6
Step 3 – Check PHP Version
$ php -v

모니위키 설치
설치하려는 디렉토리 아래(/var/www/html/) 에서
$ git clone https://github.com/wkpark/moniwiki.git
$ chown -R www-data:www-data moniwiki
$ cd moniwiki/
$ git clone https://github.com/wkpark/moniwiki-wikiseed.git wikiseed
$ cd theme/
$ git clone https://github.com/wkpark/moniwiki-theme-paper.git paper
$ git clone https://github.com/wkpark/moniwiki-theme-bootstrap3.git bootstrap3
$ git clone https://github.com/wkpark/moniwiki-theme-publish.git publish

브라우저에서 monisetup.php 접속 http://127.0.0.1/moniwiki/monisetup.php
Welcome to MoniWiki ! This is your first installation 나오면 Goto MoniSetup again to configure details 들어가서
$sitename 설정
$admin_passwd 설정
$use_sectionedit 설정
“Sow wikiseed” 로 wiki seed 심기

쉘에서 secure.sh 실행
$ sh secure.sh

그런데 http://127.0.0.1/moniwiki/wiki.php 에 들어가보면 흰 화면만 나온다. 원인을 확인하기 위해 터미널에서 다음과 같이 실행한다.
$ cd /var/www/html/moniwiki
$ php wiki.php
PHP Fatal error: Call to undefined function mb_strcut() in /var/www/html/moniwiki/wiki.php on line 4861

mb_strcut 등이 정상동작하기 위해서는 mbstring 모듈을 설치해야 한다.
$ apt install php5.6-mbstring
$ php -r "mb_strlen();" 했을 때 PHP Warning: mb_strlen() exptects.. 가 나오면 성공
$ systemctl restart apache2 로 아파치 재시작까지 해 줘야 한다. http://127.0.0.1/moniwiki/wiki.php 가 잘 나오는지 확인

설정을 다시 바꾸고 싶다면 $ sh monisetup.sh 실행한 뒤 브라우저에서 monisetup.php 를 연다.

참고
https://blog.dasomoli.org/tag/monisetup/
https://nyangnyangworld.tistory.com/4
https://tecadmin.net/install-php-ubuntu-20-04/

야마하 라디오 안테나

아파트 동축 케이블과 연결하려면?


[UE4] FPS 랙 시뮬레이션 개발 이야기

콘솔 명령어 t.MaxFPS 를 매 틱마다 랜덤하게 호출해서 랙 상황을 시뮬레이션 해 본다.
대강 Stat FPS 으로 확인해 봤을 때는 괜찮은 거 같은데 어떤지 모르겠네.

static TAutoConsoleVariable<int32> CVarMyFPSMin(TEXT("MyFPSMin"), 1, TEXT(""));
static TAutoConsoleVariable<int32> CVarMyFPSMax(TEXT("MyFPSMax"), 60, TEXT(""));

void AMyCharacter::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);

const int32 RandomFps = FMath::RandRange(CVarMyFPSMin.GetValueOnAnyThread(), CVarMyFPSMax.GetValueOnAnyThread());
GEngine->Exec(NULL, *FString::Printf(TEXT("t.MaxFPS %d"), RandomFps));
}


[UE4] SideRunner Practice

https://youtu.be/RzzpIp1XbX4 를 따라서 구현.

///////////////////////////////////////////////////////////////////////////
// UCLASS() 의 기본값은 NotBlueprintable.
// 그러나 AActor 는 Blueprintable 이고 Blueprintable 속성은 파생클래스에게도 적용되므로 ABaseLevel 도 Blueprintable 이다.
UCLASS()
class SIDERUNNER2_API ABaseLevel : public AActor {
GENERATED_BODY()

public:
ABaseLevel();

protected:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "My Triggers")
USceneComponent* DefaultSceneRoot;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "My Triggers")
UBoxComponent* Trigger;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "My Triggers")
UBoxComponent* SpawnLocation;

public:
UBoxComponent* GetTrigger() { return Trigger; }
UBoxComponent* GetSpawnLocation() { return SpawnLocation; }
};

///////////////////////////////////////////////////////////////////////////
ABaseLevel::ABaseLevel() {
// DefaultSceneRoot 없이 바로 Trigger 를 Root 로 만들면
// BP -> Details 에서 Scale, Location 값을 변경할 수 없다.
DefaultSceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("DefaultSceneRoot"));
SetRootComponent(DefaultSceneRoot);

Trigger = CreateDefaultSubobject<UBoxComponent>(TEXT("Trigger"));
Trigger->AttachToComponent(DefaultSceneRoot, FAttachmentTransformRules::KeepRelativeTransform);

SpawnLocation = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnLocation"));
SpawnLocation->AttachToComponent(DefaultSceneRoot, FAttachmentTransformRules::KeepRelativeTransform);
}

///////////////////////////////////////////////////////////////////////////
UCLASS()
class SIDERUNNER2_API ARunnerCharacter : public ACharacter {
GENERATED_BODY()

UPROPERTY(VisibleAnywhere)
class UCameraComponent* SideViewCamera;

public:
ARunnerCharacter();

protected:
virtual void BeginPlay() override;
void MoveRight(float InValue);

public:
virtual void Tick(float DeltaTime) override;
void RestartLevel();
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

private:
UFUNCTION()
void OnOverlapBegin(UPrimitiveComponent* OverlappedComp,
AActor* OtherActor, UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

float ZPosition = 0.f;
bool CanMove = false;
};

///////////////////////////////////////////////////////////////////////////
ARunnerCharacter::ARunnerCharacter() {
PrimaryActorTick.bCanEverTick = true;

UCapsuleComponent* CapsuleCom = GetCapsuleComponent();
CapsuleCom->InitCapsuleSize(42.f, 96.f);
CapsuleCom->SetCollisionResponseToChannel(ECC_GameTraceChannel1, ECR_Overlap);

bUseControllerRotationPitch = false;
bUseControllerRotationRoll = false;
bUseControllerRotationYaw = false;

SideViewCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Side View Camera"));
SideViewCamera->bUsePawnControlRotation = false;

UCharacterMovementComponent* MovementComponent = GetCharacterMovement();
MovementComponent->bOrientRotationToMovement = true;
MovementComponent->RotationRate = FRotator(0.0f, 720.0f, 0.0f);

MovementComponent->GravityScale = 2.0f;
MovementComponent->AirControl = 0.8f;
MovementComponent->JumpZVelocity = 1000.0f;
MovementComponent->GroundFriction = 3.0f;
MovementComponent->MaxWalkSpeed = 600.0f;
MovementComponent->MaxFlySpeed = 600.0f;

FVector TempPos = GetActorLocation();
ZPosition = TempPos.Z + 300.0f;
}

void ARunnerCharacter::BeginPlay() {
Super::BeginPlay();

GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &ARunnerCharacter::OnOverlapBegin);

CanMove = true;
}

void ARunnerCharacter::MoveRight(float InValue) {
if (CanMove) {
AddMovementInput(FVector(0.0f, 1.0f, 0.0f), InValue);
}
}

void ARunnerCharacter::Tick(float DeltaTime) {
Super::Tick(DeltaTime);

FVector TempPos = GetActorLocation();
TempPos.X -= 850.0f;
TempPos.Z = ZPosition;
SideViewCamera->SetWorldLocation(TempPos);
}

void ARunnerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) {
Super::SetupPlayerInputComponent(PlayerInputComponent);

PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
PlayerInputComponent->BindAxis("MoveRight", this, &ARunnerCharacter::MoveRight);
}

void ARunnerCharacter::RestartLevel() {
UGameplayStatics::OpenLevel(this, FName(*GetWorld()->GetName()));
}

void ARunnerCharacter::OnOverlapBegin(UPrimitiveComponent* OverlappedComp,
AActor* OtherActor, UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) {
if (OtherActor) {
if (AWallSpike* WallSpike = Cast<AWallSpike>(OtherActor)) {
USkeletalMeshComponent* InMesh = GetMesh();
InMesh->Deactivate();
InMesh->SetVisibility(false);

CanMove = false;

FTimerHandle UnusedHandle;
GetWorldTimerManager().SetTimer(UnusedHandle, this, &ARunnerCharacter::RestartLevel, 2.f, false);
}
}
}

///////////////////////////////////////////////////////////////////////////
UCLASS()
class SIDERUNNER2_API ASpawnLevel : public AActor {
GENERATED_BODY()

protected:
virtual void BeginPlay() override;

public:
UFUNCTION()
void SpawnLevel(bool IsFirst);

UFUNCTION()
void OnOverlapBegin(UPrimitiveComponent* OverlappedComp,
AActor* OtherActor, UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

protected:
UPROPERTY(EditAnywhere)
TArray<TSubclassOf<ABaseLevel>> LevelClasses;

TArray<ABaseLevel*> LevelList;
};

///////////////////////////////////////////////////////////////////////////
void ASpawnLevel::BeginPlay() {
Super::BeginPlay();

// 미리 레벨을 4개 스폰해 둔다.
SpawnLevel(true);
SpawnLevel(false);
SpawnLevel(false);
SpawnLevel(false);
}

void ASpawnLevel::SpawnLevel(bool IsFirst) {
if (LevelClasses.Num() <= 0) { return; }

FVector SpawnLocation = FVector(0.f, 1000.f, 0.f);
FRotator SpawnRotation = FRotator(0, 90, 0);

if (!IsFirst) {
ABaseLevel* LastLevel = LevelList.Last();
SpawnLocation = LastLevel->GetSpawnLocation()->GetComponentTransform().GetTranslation();
SpawnRotation = FRotator(0, 90, 0);
}

const int32 RandomLevel = FMath::RandRange(0, LevelClasses.Num() - 1);
FActorSpawnParameters SpawnInfo;
if (ABaseLevel* NewLevel = GetWorld()->SpawnActor<ABaseLevel>(LevelClasses[RandomLevel], SpawnLocation, SpawnRotation, SpawnInfo)) {
if (UBoxComponent* Trigger = NewLevel->GetTrigger()) {
Trigger->OnComponentBeginOverlap.AddDynamic(this, &ASpawnLevel::OnOverlapBegin);
}

LevelList.Add(NewLevel);
if (LevelList.Num() > 5) {
LevelList.RemoveAt(0);
}
}
}

void ASpawnLevel::OnOverlapBegin(UPrimitiveComponent* OverlappedComp,
AActor* OtherActor, UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
SpawnLevel(false);
}

///////////////////////////////////////////////////////////////////////////
UCLASS()
class SIDERUNNER2_API AWallSpike : public AActor {
GENERATED_BODY()

public:
AWallSpike();
virtual void Tick(float DeltaTime) override;
};

///////////////////////////////////////////////////////////////////////////
static TAutoConsoleVariable<float> CVarWallSpikeSpeed(TEXT("WallSpikeSpeed"), 350.f, TEXT(""));

AWallSpike::AWallSpike() {
PrimaryActorTick.bCanEverTick = true;
}

void AWallSpike::Tick(float DeltaTime) {
Super::Tick(DeltaTime);

SetActorLocation(GetActorLocation() + FVector(0, CVarWallSpikeSpeed.GetValueOnGameThread() * DeltaTime, 0), true);
}


NuRi's Tools - iframe 변환기


1 2 3 4 5 6 7 8 9 10 다음


Yes24위대한게임의탄생3

위대한 게임의 탄생 3
예스24 | 애드온2